/** utility typescript type and interface definitions. * * @module */ /** get the constructor function of type `T` */ export type ConstructorOf = new (...args: Args) => T; /** get the prototype object of a class `CLS` */ export type PrototypeOf = CLS extends { new (...args: any[]): infer U; } ? U : never; /** turn optional properties `P` of interface `T` into required */ export type Require = Omit & Required>; /** turn properties `P` of interface `T` into optional */ export type Optional = Omit & Partial>; /** extract all optional fields from type `T` */ export type OptionalKeysOf = { [K in keyof T as (undefined extends T[K] ? K : never)]: T[K]; }; /** get all non-symbol property keys of a particular type `T`. */ export type NonSymbolKeys = { [K in keyof T]: K extends symbol ? never : K; }[keyof T]; /** @deprecated * use {@link MembersOf} instead */ export type ClassFieldsOf = { [K in keyof T as (T[K] extends Function ? never : K)]: T[K]; }; /** get all methods of a class-instance */ export type MethodsOf = { [K in keyof T as (T[K] extends Function ? K : never)]: T[K]; }; /** get all functions of a class-instance */ export type CallableFunctionsOf = { [K in keyof T as (T[K] extends (CallableFunction & ((this: T, ...args: any) => any)) ? K : never)]: T[K]; }; /** get all data members (non-methods) of a class-instance */ export type MembersOf = Omit>; /** map each entry (key-value pair) of an object, to a tuple of the key and its corresponding value. * * the output of this type is what the builtin `Object.entries` static method should ideally return if it were typed strictly. * * @example * ```ts * const obj = { kill: "your", self: "ok", tomorrow: 420 } as const * type EntriesOfObj = EntriesOf * // the IDE will now infer the type to be: * // `type EntriesOfObj = Array<["kill", "your"] | ["self", "ok"] | ["tomorrow", 420]>` * // had we not used the `as const` narrowing utility, the output would've then been: * // `type EntriesOfObj = Array<["kill", string] | ["self", string] | ["tomorrow", number]>` * ``` */ export type EntriesOf = Array<{ [K in keyof T]: [key: K, value: T[K]]; }[keyof T]>; /** turn all fields of an object `T` to optional, deeply. * * > [!note] * > we exclude many built-in types and classes so that they are not turned into partial types. * > here is the full list of built-in types and classes (aside from primitives) that are not turned into partial objects: * > * > `Function | Array | Set | Map | WeakSet | WeakMap | TypedArray | URL | String | BigInt | Number | Boolean | Symbol` * * @example * ```ts * const my_obj = { * a: 1, * b: { c: 2 }, * d: { e: { f: 3 }, g: 4 }, * h: { i: [{ j: 5 }, { k: 6 }] }, * l: { m: ((arg: string) => "hello") }, * n: new URL("https://example.com"), * o: new Map([["a", 1], ["b", 2]]), * } as const * * type DeeplyPartial_my_obj = DeepPartial * type ManuallyConstructed_DeeplyPartial_my_obj = { * a?: 1, * b?: { c?: 2 }, * d?: { e?: { f?: 3 }, g?: 4 }, * h?: { i?: readonly [_0?: { j?: 5 } | undefined, _1?: { k?: 6 } | undefined] }, * l?: { m?: ((arg: string) => string) }, * n?: URL, * o?: Map, * } * * type BothTypesAreEqual_1 = DeeplyPartial_my_obj extends ManuallyConstructed_DeeplyPartial_my_obj ? true : false * type BothTypesAreEqual_2 = ManuallyConstructed_DeeplyPartial_my_obj extends DeeplyPartial_my_obj ? true : false * * const temp: true = true * temp satisfies BothTypesAreEqual_1 * temp satisfies BothTypesAreEqual_2 * ``` */ export type DeepPartial = T extends (Function | Array | Set | Map | WeakSet | WeakMap | TypedArray | URL | String | BigInt | Number | Boolean | Symbol) ? T : T extends Record ? { [P in keyof T]?: DeepPartial; } : T; /** turn all fields of an object `T` to required, deeply. * * > [!note] * > we exclude many built-in types and classes so that they are not turned into required types. * > here is the full list of built-in types and classes (aside from primitives) that are not turned into required objects: * > * > `Function | Array | Set | Map | WeakSet | WeakMap | TypedArray | URL | String | BigInt | Number | Boolean | Symbol` * * @example * ```ts * type MyType = { * a?: 1, * b: { c?: 2 }, * d: { e?: { f: 3 }, g?: 4 }, * h: { i?: [_0?: { j?: 5 } | undefined, _1?: { k?: 6 } | undefined] }, * l?: { m?: ((arg: string) => string), n: 7 | undefined, o?: 8 | undefined }, * } * * type MyType_DeeplyRequired = DeepRequired * * type ManuallyConstructed_MyType_DeeplyRequired = DeepRequired<{ * a: 1, * b: { c: 2 }, * d: { e: { f: 3 }, g: 4 }, * h: { i: [_0?: { j?: 5 } | undefined, _1?: { k?: 6 } | undefined] }, * l: { m: ((arg: string) => string), n: 7 | undefined, o: 8 }, * }> * * type BothTypesAreEqual_1 = MyType_DeeplyRequired extends ManuallyConstructed_MyType_DeeplyRequired ? true : false * type BothTypesAreEqual_2 = ManuallyConstructed_MyType_DeeplyRequired extends MyType_DeeplyRequired ? true : false * * const temp: true = true * temp satisfies BothTypesAreEqual_1 * temp satisfies BothTypesAreEqual_2 * ``` */ export type DeepRequired = T extends (Function | Array | Set | Map | WeakSet | WeakMap | TypedArray | URL | String | BigInt | Number | Boolean | Symbol) ? T : T extends Record ? { [P in keyof T]-?: DeepRequired; } : T; /** get the stringified type name of a type-parameter. */ export type TypeName = T extends string ? "string" : T extends BigInt ? "bigint" : T extends number ? "number" : T extends boolean ? "boolean" : T extends undefined ? "undefined" : T extends symbol ? "symbol" : T extends Function ? "function" : T extends Array ? "array" : T extends null ? "null" : "object"; /** add a prefix `PRE` to all property names of object `T` */ export type PrefixProps = { [K in keyof T & string as `${PRE}${K}`]: T[K]; }; /** add a postfix (suffix) `POST` to all property names of object `T` */ export type PostfixProps = { [K in keyof T & string as `${K}${POST}`]: T[K]; }; /** allows one to declare static interface `CONSTRUCTOR` that must be implemented by a class `CLASS`. * * > [!important] * > your `CONSTRUCTOR` static interface **must** contain a constructor method in it. * > although, that constructor could be super generalized too, despite the other static methods being narrowly defined. * > take the following for instance: * * ```ts * // interface for a class that must implement a static `clone` method, which should return a clone of the provided object `obj`, but omit numeric keys * interface Cloneable { * constructor(...args: any[]): any * clone(obj: T): Omit * } * ``` * * to use this utility type, you must provide the static interface as the first parameter, * and then `typeof CLASS_NAME` (which is the name of the class itself) as the second parameter. * * @example * ```ts * interface Stack { * push(...items: T[]): void * pop(): T | undefined * clear(): T[] * } * * interface CloneableStack { * new (...args: any[]): Stack * // this static method should remove all function objects from the stack * clone(original_stack: Stack): Stack> * } * * const stack_class_alias = class MyStack implements StaticImplements { * arr: T[] * constructor(first_item?: T) { * this.arr = first_item === undefined ? [] : [first_item] * } * * push(...items: T[]): void { this.arr.push(...items) } * pop(): T | undefined { return this.arr.pop() } * clear(): T[] { return this.arr.splice(0) } * * static clone(some_stack: Stack) { * const arr_no_func = (some_stack as MyStack).arr.filter((v) => typeof v !== "function") as Array> * const new_stack = new this>() * new_stack.push(...arr_no_func) * return new_stack * } * } * ``` */ export type StaticImplements any, CLASS extends CONSTRUCTOR> = InstanceType; /** `DecrementNumber[N]` returns `N-1`, for up to `N = 10` */ export type DecrementNumber = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; /** `IncrementNumber[N]` returns `N+1`, for up to `N = 10` */ export type IncrementNumber = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; /** repeat a string `S` for up to `N = 10` times */ export type RepeatString = N extends 1 ? S : `${S}${RepeatString}`; /** create an element-wise intersection between two tuples. * * > [!note] * > the intersection `any & T` typically produces `any`, * but when put through this utility type, it will produce `T` for convenience of usage with function parameters intersection. * * @example * ```ts * type A = TupleIntersect<[number, unknown, string, any], [5, number, string, boolean, 99]> * // A === [5, number, string, boolean] * ``` */ export type TupleIntersect = N extends number ? IntersectKnown extends (undefined | never) ? [] : [ IntersectKnown, ...TupleIntersect ] : []; /** create an element-wise intersection between two tuples. note that the intersection `any & T` does not produce `T` for some reason unfortunately. * @example * ```ts * type A = TupleUnion<[number, unknown, string, boolean], [5, number, string, any, 99]> * // A === [number, number, string, boolean>, undefined | 99] * ``` */ export type TupleUnion = N extends number ? UnionKnown extends (undefined | never) ? [] : [ UnionKnown, ...TupleUnion ] : []; /** perform a union between two types, making sure that if either is `unknown`, then it'll be treated as `never`. * * why is this useful? because in typescript's `unknown` is a supertype of all types (similar to `any`), which means that something like `T | unknown = unknown`. * thus, in a scenario where such a behavior is not desired, you can use this utility type: `UnionKnown = T` */ export type UnionKnown = (unknown extends A ? B : A) | (unknown extends B ? A : B); /** perform an intersection between two types, making sure that if either is `unknown` or `any`, then it'll be ignored, and only the known type will persevere. * * why is this useful? because in typescript's `any` is a subtype of all types, which means that something like `T & any = any` (strangely unintuitive). * thus, in a scenario where such a behavior is not desired, you can use this utility type: `UnionKnown = T` */ export type IntersectKnown = (unknown extends A ? B : A) & (unknown extends B ? A : B); /** this utility type lets makes your typescript LSP auto-suggest literals defined in the input generic type `T`, * while also permitting arbitrary strings to be used. * * @example * ```ts * type InstallationPath = AutoSuggestOrString<0 | undefined | "$CWD" | "C-DRIVE" | "$ROOT"> * * const installProgram = async (installation_path: InstallationPath) => { * const abs_path = installation_path === undefined ? "" * : installation_path === "$CWD" ? Deno.cwd() // LSP will suggest `0 | "$CWD" | "C-DRIVE" | "$ROOT"`. * : installation_path === "C-DRIVE" ? "C:/" // LSP will suggest `0 | "C-DRIVE" | "$ROOT"`. * : installation_path === "$ROOT" ? "/" // LSP will suggest `0 | "$ROOT"`. * : installation_path === 0 ? "" // LSP will suggest `0`. * : installation_path satisfies string // `(string & {})` is still a valid string. * // perform installation * } * * await installProgram("$CWD") // valid, and LSP will suggest the default options first. * await installProgram(undefined) // valid. * await installProgram(0) // valid. * await installProgram("/etc/hello/world") // also valid. * ``` */ export type AutoSuggestOrString = T | (string & {}); /** an array of type `T`, and fixed length `L`. * * this technique was copied from [stackexchange, user "mstephen19"](https://stackoverflow.com/a/73384647). * * the generic `R` type parameter is for recursion, and not intended for external use. */ export type ArrayFixedLength = R["length"] extends L ? R : ArrayFixedLength; /** represents a scalar mathematical function of `ParamLength` number of input parameters (or variables). * * for instance, a scalar addition function is merely a mapping from domains: * $X,Y \in \R$ to $Z \in \R$: $\text{Add} : X \times Y \rightarrow Z$ . * * ```ts * const add_func: NumericMapFunc<2> = (x, y) => x + y * ``` */ export type NumericMapFunc = (...params: ArrayFixedLength) => number; /** represents a higher-order scalar function of `ParamLength` number of array input parameters, which are then manipulated based on index `i`, for all possible `i`. * * for instance, to model an array addition function, you would simply do: * * ```ts * const add_hof: IndexNumericMapFunc<2> = (arrX, arrY) => (i) => arrX[i] + arrY[i] * ``` */ export type IndexNumericMapFunc = (...params: ArrayFixedLength) => (i: number) => number; /** unsigned integer, signed integer, or IEEE-754 float */ export type NumericFormatType = "u" | "i" | "f"; /** little-endian, big-endian, clamped 1-byte, or 1-byte */ export type NumericEndianType = "l" | "b"; /** specify 1-byte, 2-bytes, 4-bytes, or 8-bytes of numeric data*/ export type DByteSize = "1" | "2" | "4" | "8"; /** indicates the name of a numeric type. * * the collection of possible valid numeric types is: * - `"u1"`, `"u2"`, `"u4"`, `"u8"`, `"i1"`, `"i2"`, `"i4"`, `"i8"`, `"f4"`, `"f8"`, `"u1c"` * * the first character specifies the format: * - `u` = unsigned integer * - `i` = signed integer * - `f` = float IEEE-754 * * the second character specifies the byte-size: * - `1` = one byte * - `2` = two bytes (short) * - `4` = four bytes (word) * - `8` = eight bytes (long) */ export type NumericDType = Exclude<`${NumericFormatType}${DByteSize}` | "u1c", "f1" | "f2" | "u8" | "i8">; /** abstract constructor of any typed array, such as `new Uint8Array(...)` * you can narrow down the constructor through the use of a {@link NumericDType} string annotation * @example * ```ts * const clamp_arr_constructor: TypedArrayConstructor<"u1c"> = Uint8ClampedArray * ``` */ export type TypedArrayConstructor = { "u1": Uint8ArrayConstructor; "u1c": Uint8ClampedArrayConstructor; "u2": Uint16ArrayConstructor; "u4": Uint32ArrayConstructor; "i1": Int8ArrayConstructor; "i2": Int16ArrayConstructor; "i4": Int32ArrayConstructor; "f4": Float32ArrayConstructor; "f8": Float64ArrayConstructor; }[DType]; /** an instance of any typed array, such as `Uint8Array` * you can narrow down the type through the use of a {@link NumericDType} string annotation * @example * ```ts * const clammped_bytes_arr: TypedArray<"u1c"> = new Uint8ClampedArray(42) * ``` */ export type TypedArray = { "u1": Uint8Array; "u1c": Uint8ClampedArray; "u2": Uint16Array; "u4": Uint32Array; "i1": Int8Array; "i2": Int16Array; "i4": Int32Array; "f4": Float32Array; "f8": Float64Array; }[DType]; /** any numeric array */ export type NumericArray = TypedArray | Array; /** indicates the name of a numeric type with required endian information, or the use of a variable-sized integer. * * the collection of possible valid numeric types is: * - `"u1"`, `"i1"`, `"u2l"`, `"u2b"`, `"i2l"`, `"i2b"`, `"u4l"`, `"u4b"`, `"u8l"`, `"u8b"`, `"i4l"`, `"i4b"`, `"i8l"`, `"i8b"`, `"f4l"`, `"f4b"`, `"f8l"`, `"f8b"`, `"u1c"`, * * the first character specifies the format: * - `u` = unsigned integer * - `i` = signed integer * - `f` = float IEEE-754 * * the second character specifies the byte-size: * - `1` = one byte * - `2` = two bytes (short) * - `4` = four bytes (word) * - `8` = eight bytes (long) * * the third character specifies the endianness. but in the case of unsigned one byte integers, the `c` character specifies if the value is clamped to 255: * - `l` = little endian * - `b` = big endian * - `c` = clamped (only valid for `"u1c"` type) * * for variable byte sized numbers, use {@link VarNumericType}. */ export type NumericType = Exclude<`${NumericDType}${NumericEndianType}` | "u1" | "u1c" | "i1", `${"u1" | "u1c" | "i1"}${NumericEndianType}`>; /** an array (regular javascript array) of numbers can be interpreted as an array of formatted binary numbers. */ export type NumericArrayType = `${NumericType}[]`; /** indicates either a variable bytes sized unsigned or signed integer. see [wikipedia](https://en.wikipedia.org/wiki/Variable-length_quantity) to understand how they're represented in binary. */ export type VarNumericType = "uv" | "iv"; /** numeric array version of {@link VarNumericType}. */ export type VarNumericArrayType = `${VarNumericType}[]`; /** a float number in the range `0.0` to `1.0` (inclusive) */ export type UnitInterval = number; export declare const isUnitInterval: (value: number) => value is UnitInterval; /** an integer number in the range `0` to `255` (inclusive) */ export type UByte = number; export declare const isUByte: (value: number) => value is UByte; /** a float number in the range `0` to `360` (inclusive), indicating the degree rotation angle. */ export type Degrees = number; export declare const isDegrees: (value: number) => value is Degrees; /** a float number in the range `0` to `pi` (inclusive), indicating the radian rotation angle. */ export type Radians = number; export declare const isRadians: (value: number) => value is Radians; /** represents either a regular 2d html canvas context, or an offscreen 2d canvas's context. */ export type Ctx2D = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D; /** represents either a regular value `T` or a `Promise` thereof. */ export type MaybePromise = T | Promise; /** represents either a regular value `T` or a `PromiseLike` thereof. */ export type MaybePromiseLike = T | PromiseLike; /** the type definition of a `Promise` resolver function. */ export type PromiseResolver = ((value: T | PromiseLike) => void); /** the type definition of a `Promise` rejector function. */ export type PromiseRejector = ((reason?: any) => void); /** represents a typical javasctipt object, something that pairs `keys` with `values` */ export type Obj = { [key: PropertyKey]: any; }; /** represents an empty javasctipt object */ export type EmptyObj = { [key: PropertyKey]: never; }; //# sourceMappingURL=typedefs.d.ts.map