From 52d392aefedda494608f8a37057f652edf228172 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Tue, 26 Nov 2024 19:00:19 +0100 Subject: [PATCH] feat: ValueGen, StringGen, consumeGen() and consumeStringGen() --- .changeset/three-suns-sleep.md | 5 ++ README.md | 101 +++++++++++++++++++++++++++++++-- lib/misc.ts | 42 +++++++++++++- lib/types.ts | 2 +- 4 files changed, 144 insertions(+), 6 deletions(-) create mode 100644 .changeset/three-suns-sleep.md diff --git a/.changeset/three-suns-sleep.md b/.changeset/three-suns-sleep.md new file mode 100644 index 0000000..f9decd2 --- /dev/null +++ b/.changeset/three-suns-sleep.md @@ -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 diff --git a/README.md b/README.md index be9dbf5..b5291fa 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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

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

+### 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. + +
Example - click to view + +```ts +import { consumeGen, type ValueGen } from "@sv443-network/userutils"; + +async function doSomething(value: ValueGen) { + // type gets inferred because `value` is correctly typed as a ValueGen + 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); +``` + +
+ +

+ +### consumeStringGen() +Usage: +```ts +consumeStringGen(strGen: StringGen): Promise +``` + +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. + +
Example - click to view + +```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, "
"); + } + + // ... +} +``` + +
+ +

+ ## Arrays: @@ -2528,7 +2596,7 @@ logSomething(barObject); // Type error
-## NonEmptyArray +### NonEmptyArray Usage: ```ts NonEmptyArray @@ -2558,7 +2626,7 @@ logFirstItem(["04abc", "69"]); // 4
-## NonEmptyString +### NonEmptyString Usage: ```ts NonEmptyString @@ -2582,7 +2650,7 @@ convertToNumber(""); // type error: Argument of type 'string' is not assign
-## LooseUnion +### LooseUnion Usage: ```ts LooseUnion @@ -2609,7 +2677,7 @@ foo(1); // type error: Argument of type '1' is not assignable to parameter of
-## Prettify +### Prettify Usage: ```ts Prettify @@ -2662,6 +2730,31 @@ const bar: Bar = { ``` +

+ +### ValueGen +Usage: +```ts +ValueGen +``` + +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. + +

+ +### StringGen +Usage: +```ts +StringGen +``` + +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. +



diff --git a/lib/misc.ts b/lib/misc.ts index 00581cb..ea44a1b 100644 --- a/lib/misc.ts +++ b/lib/misc.ts @@ -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 { +export async function fetchAdvanced(input: string | RequestInfo | URL, options: FetchAdvancedOpts = {}): Promise { const { timeout = 10000 } = options; const { signal, abort } = new AbortController(); @@ -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 | Promise | (() => TValueType | Promise); + +/** + * Turns a {@linkcode ValueGen} into its final value. + * @template TValueType The type of the value that the ValueGen should yield + */ +export async function consumeGen(valGen: ValueGen): Promise { + return await (typeof valGen === "function" + ? (valGen as (() => Promise | 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; + +/** + * 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(strGen: StringGen): Promise { + return ( + typeof strGen === "string" + ? strGen + : String( + typeof strGen === "function" + ? await strGen() + : strGen + ) + ) as TStrUnion; +} diff --git a/lib/types.ts b/lib/types.ts index e9234e4..c77f08f 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -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.