Skip to content

Commit

Permalink
feat: ValueGen, StringGen, consumeGen() and consumeStringGen()
Browse files Browse the repository at this point in the history
  • Loading branch information
Sv443 committed Nov 26, 2024
1 parent 4acb812 commit 52d392a
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/three-suns-sleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@sv443-network/userutils": minor
---

Added `ValueGen` and `StringGen` types with accompanying `consumeGen()` and `consumeStringGen()` functions to allow for super flexible typing and declaration of values
101 changes: 97 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ View the documentation of previous major releases:
- [`decompress()`](#decompress) - decompress a previously compressed string
- [`computeHash()`](#computehash) - compute the hash / checksum of a string or ArrayBuffer
- [`randomId()`](#randomid) - generate a random ID of a given length and radix
- [`consumeGen()`](#consumegen) - consumes a ValueGen and returns the value
- [`consumeStringGen()`](#consumestringgen) - consumes a StringGen and returns the string
- [**Arrays:**](#arrays)
- [`randomItem()`](#randomitem) - returns a random item from an array
- [`randomItemIndex()`](#randomitemindex) - returns a tuple of a random item and its index from an array
Expand All @@ -89,6 +91,8 @@ View the documentation of previous major releases:
- [`NonEmptyString`](#nonemptystring) - any string that should have at least one character
- [`LooseUnion`](#looseunion) - a union that gives autocomplete in the IDE but also allows any other value of the same type
- [`Prettify`](#prettify) - expands a complex type into a more readable format while keeping functionality the same
- [`ValueGen`](#valuegen) - a "generator" value that allows for super flexible value typing and declaration
- [`StringGen`](#stringgen) - a "generator" string that allows for super flexible string typing and declaration, including support for unions

<br><br>

Expand Down Expand Up @@ -2037,6 +2041,70 @@ benchmark(true, true); // Generated 10k in 1054ms

<br><br>

### consumeGen()
Usage:
```ts
consumeGen(valGen: ValueGen):
```

Turns a [`ValueGen`](#valuegen) into its final value.
ValueGen allows for tons of flexibility in how the value can be obtained. Calling this function will resolve the final value.

<details><summary><b>Example - click to view</b></summary>

```ts
import { consumeGen, type ValueGen } from "@sv443-network/userutils";

async function doSomething(value: ValueGen<number>) {
// type gets inferred because `value` is correctly typed as a ValueGen<number>
const finalValue = await consumeGen(value);
console.log(finalValue);
}

// the following are all valid and yield 42:
doSomething(42);
doSomething(() => 42);
doSomething(Promise.resolve(42));
doSomething(async () => 42);
```

</details>

<br><br>

### consumeStringGen()
Usage:
```ts
consumeStringGen(strGen: StringGen): Promise<string>
```

Turns a [`StringGen`](#stringgen) into its final string value.
StringGen allows for tons of flexibility in how the string can be obtained. Calling this function will resolve the final string.
Optionally you can use the template parameter to define the union of strings that the StringGen should yield.

<details><summary><b>Example - click to view</b></summary>

```ts
import { consumeStringGen, type StringGen } from "@sv443-network/userutils";

export class MyTextPromptThing {
// full flexibility on how to pass the string:
constructor(private text: StringGen) {}

/** Returns the HTML content to show in the prompt */
private async getContent() {
const promptText = await consumeGen(this.text);
return promptText.trim().replace(/\n/g, "<br>");
}

// ...
}
```

</details>

<br><br>

<!-- #region Arrays -->
## Arrays:

Expand Down Expand Up @@ -2528,7 +2596,7 @@ logSomething(barObject); // Type error

<br>

## NonEmptyArray
### NonEmptyArray
Usage:
```ts
NonEmptyArray<TItem = unknown>
Expand Down Expand Up @@ -2558,7 +2626,7 @@ logFirstItem(["04abc", "69"]); // 4

<br>

## NonEmptyString
### NonEmptyString
Usage:
```ts
NonEmptyString<TString extends string>
Expand All @@ -2582,7 +2650,7 @@ convertToNumber(""); // type error: Argument of type 'string' is not assign

<br>

## LooseUnion
### LooseUnion
Usage:
```ts
LooseUnion<TUnion extends string | number | object>
Expand All @@ -2609,7 +2677,7 @@ foo(1); // type error: Argument of type '1' is not assignable to parameter of

<br>

## Prettify
### Prettify
Usage:
```ts
Prettify<T>
Expand Down Expand Up @@ -2662,6 +2730,31 @@ const bar: Bar = {
```
</details>

<br><br>

### ValueGen
Usage:
```ts
ValueGen<TValueType>
```

A type that describes a value that can be obtained in various ways.
Those include the type itself, a function that returns the type, a Promise that resolves to the type or either a sync or an async function that returns the type.
This type is used in the [`consumeGen()`](#consumegen) function to convert it to the type it represents. Refer to that function for an example.

<br><br>

### StringGen
Usage:
```ts
StringGen<TStrUnion>
```

A type that describes a string that can be obtained in various ways.
Those include the type itself, a function that returns the type, a Promise that resolves to the type or either a sync or an async function that returns the type.
Contrary to [`ValueGen`](#valuegen), this type allows for specifying a union of strings that the StringGen should yield, as long as it is loosely typed as just `string`.
It is used in the [`consumeStringGen()`](#consumestringgen) function to convert it to a plain string. Refer to that function for an example.

<br><br><br><br>

<!-- #region Footer -->
Expand Down
42 changes: 41 additions & 1 deletion lib/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export type FetchAdvancedOpts = Prettify<
>;

/** Calls the fetch API with special options like a timeout */
export async function fetchAdvanced(input: RequestInfo | URL, options: FetchAdvancedOpts = {}): Promise<Response> {
export async function fetchAdvanced(input: string | RequestInfo | URL, options: FetchAdvancedOpts = {}): Promise<Response> {
const { timeout = 10000 } = options;
const { signal, abort } = new AbortController();

Expand All @@ -98,3 +98,43 @@ export async function fetchAdvanced(input: RequestInfo | URL, options: FetchAdva
throw err;
}
}

/**
* A ValueGen value is either its type, a promise that resolves to its type, or a function that returns its type, either synchronous or asynchronous.
* ValueGen allows for the utmost flexibility when applied to any type, as long as {@linkcode consumeGen()} is used to get the final value.
* @template TValueType The type of the value that the ValueGen should yield
*/
export type ValueGen<TValueType> = TValueType | Promise<TValueType> | (() => TValueType | Promise<TValueType>);

/**
* Turns a {@linkcode ValueGen} into its final value.
* @template TValueType The type of the value that the ValueGen should yield
*/
export async function consumeGen<TValueType>(valGen: ValueGen<TValueType>): Promise<TValueType> {
return await (typeof valGen === "function"
? (valGen as (() => Promise<TValueType> | TValueType))()
: valGen
)as TValueType;
}

/**
* A StringGen value is either a string, anything that can be converted to a string, or a function that returns one of the previous two, either synchronous or asynchronous, or a promise that returns a string.
* StringGen allows for the utmost flexibility when dealing with strings, as long as {@linkcode consumeStringGen()} is used to get the final string.
*/
export type StringGen = ValueGen<Stringifiable>;

/**
* Turns a {@linkcode StringGen} into its final string value.
* @template TStrUnion The union of strings that the StringGen should yield - this allows for finer type control compared to {@linkcode consumeGen()}
*/
export async function consumeStringGen<TStrUnion extends string>(strGen: StringGen): Promise<TStrUnion> {
return (
typeof strGen === "string"
? strGen
: String(
typeof strGen === "function"
? await strGen()
: strGen
)
) as TStrUnion;
}
2 changes: 1 addition & 1 deletion lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//#region UU types

/** Represents any value that is either a string itself or can be converted to one (implicitly and explicitly) because it has a toString() method */
export type Stringifiable = string | { toString(): string };
export type Stringifiable = string | { toString(): string } | { [Symbol.toStringTag]: string } | number | boolean | null | undefined;

/**
* A type that offers autocomplete for the passed union but also allows any arbitrary value of the same type to be passed.
Expand Down

0 comments on commit 52d392a

Please sign in to comment.