import { type Merge, type NonNever, type PickProperties, type StrictOmit, type UnionToIntersection, type Writable } from 'ts-essentials'; import { type Maybe } from './value/maybe.type'; /** * Boolean, string or number value. */ export type PrimativeValue = boolean | string | number; /** * Class typing, restricted to types that have a constructor via the new keyword. */ export type ClassType = { new (...args: unknown[]): T; }; export type ObjectWithConstructor = { constructor: Function; }; /** * Returns true if the input is a function-like value with a prototype and constructor (i.e., a class or named function declaration). * Returns false for arrow functions, class instances, plain objects, and primitives. * * @param obj - The value to check. * @returns Whether the value is a function with a constructor. */ export declare function isObjectWithConstructor(obj: any): obj is ObjectWithConstructor; /** * Returns true if the input is a class (requires `new` to instantiate). Distinguishes classes from regular functions * by checking that the prototype is non-writable. * * @param obj - The value to check. * @returns Whether the value is a class type. */ export declare function isClassLikeType(obj: unknown): obj is ClassLikeType; export type FunctionType = 'function' | 'class' | 'arrow'; /** * Determines the function type of the input value: `'class'`, `'function'`, or `'arrow'`. * Returns `null` if the input is not a function. * * @param x - The value to inspect. * @returns The {@link FunctionType}, or `null` for non-functions. */ export declare function getFunctionType(x: unknown): Maybe; /** * Returns true if the input is a function but not a class (i.e., a regular function or arrow function). * * @param x - The value to check. * @returns Whether the value is a non-class function. */ export declare function isNonClassFunction(x: unknown): x is Function; /** * Similar to ClassType, but allows for abstract classes. */ export type ClassLikeType = abstract new (...args: unknown[]) => T; /** * Special type used to defined other type definitions that state the defined type has every key of one type, but each key has a single/new value type. */ export type KeyValueTransformMap = { [K in X]: V; }; export type StringKeyValueTransformMap = { [K in keyof T as string]: V; }; export type KeysAsStrings = { [K in keyof T as string]: T[K]; }; export type ValuesTypesAsArray = T[keyof T][]; /** * Converts the input value to a string, if possible. Never otherwise. */ export type KeyAsString = `${KeyCanBeString}`; export type KeyCanBeString = K extends number | boolean | string | null | undefined ? K : never; export type BooleanKeyValueTransformMap = KeyValueTransformMap; /** * Merges the types T and R, but replaces keys within T with those in R. */ export type MergeReplace = Merge; /** * Similar to MergeReplace, but only allows keys that are defined within T. */ export type Replace = StrictOmit, Exclude>; /** * Similar to Replace, but all types that were not replaced are set to the third type (default unknown). */ export type ReplaceType = { [K in keyof I]: K extends keyof O ? O[K] : X; }; export type OnlyStringKeys = PickProperties; export type RemoveIndex = { [K in keyof T as string extends K ? never : number extends K ? never : K]: T[K]; }; /** * Custom typing used to only retain known keys on types that have a [key: string] in their type. * * https://stackoverflow.com/questions/51954558/how-can-i-remove-a-wider-type-from-a-union-type-without-removing-its-subtypes-in/51955852#51955852 */ export type KnownKeys = keyof RemoveIndex; /** * Makes the input key(s) required. */ export type RequiredOnKeys = K extends keyof T ? Omit & Required> : T; /** * Makes the input key(s) partials. */ export type PartialOnKeys = K extends keyof T ? Omit & Partial> : T; /** * Returns only properties that have string keys. */ export type StringKeyProperties = NonNever<{ [K in keyof T]: K extends string ? T[K] : never; }>; /** * Returns the name of all keys that are strings. */ export type StringKeyPropertyKeys = keyof StringKeyProperties; /** * Makes a readonly type able to be configured. Useful for configurating readonly types before they are used. */ export type Configurable = Writable; /** * StringOrder of all keys of an object. * * NOTE: Intellisense may not return the correct order. */ export type CommaSeparatedKeyOrderOfObject = CommaSeparatedKeyOrder<`${KeyCanBeString}`>; export type CommaSeparatedKeyOrder = StringOrder; /** * StringCombinations of all keys of an object. */ export type CommaSeparatedKeyCombinationsOfObject = CommaSeparatedKeyCombinations<`${KeyCanBeString}`>; export type CommaSeparatedKeyCombinations = StringCombination; /** * StringConcatenationApproximation of keys of an object in approximate order. */ export type CommaSeparatedKeysOfObject = CommaSeparatedKeys<`${KeyCanBeString}`>; export type CommaSeparatedKeys = StringConcatenationApproximation; /** * StringConcatenation of all keys of an object in no particular order. * * May fail for more complex types, requiring the use of CommaSeparatedKeysOfObject. */ export type AllCommaSeparatedKeysOfObject = AllCommaSeparatedKeys<`${KeyCanBeString}`>; export type AllCommaSeparatedKeys = StringConcatenation; /** * StringConcatenationOrder of all keys of an object in ascending order. * * NOTE: Intellisense may not return the correct order. */ export type OrderedCommaSeparatedKeysOfObject = OrderedCommaSeparatedKeys<`${KeyCanBeString}`>; export type OrderedCommaSeparatedKeys = StringConcatenationOrder; export type UnionToOvlds = UnionToIntersection void : never>; export type PopUnion = UnionToOvlds extends (a: infer A) => void ? A : never; /** * A type that merges all combinations of strings together using a separator, but restricts the result to ascending lexigraphical order. * * NOTE: Intellisense may not display the correct order, but Typescript will enforce the expected order. * * Example: * 'a' | 'b' | 'c' w/ ',' -> 'a' | 'b' | 'c' | 'a,b' | 'a,c' | 'a,b,c' | etc... * * Credit to: * * https://stackoverflow.com/a/65157132 */ export type StringOrder = PopUnion extends infer SELF ? SELF extends string ? Exclude extends never ? SELF : // This works because the values of S are always sorted and interpreted in an ascending order `${StringOrder, SEPARATOR>}${SEPARATOR}${SELF}` | StringOrder, SEPARATOR> | SELF : never : never; /** * A type that merges all combinations of strings together using a separator. * * Example: * 'a' | 'b' | 'c' w/ ',' -> 'a' | 'b' | 'c' | 'a,b' | 'b,a' | 'c,a,b' | etc... */ export type StringCombination = PopUnion extends infer SELF ? SELF extends string ? Exclude extends never ? SELF : `${StringCombination, SEPARATOR>}${SEPARATOR}${SELF}` | `${SELF}${SEPARATOR}${StringCombination, SEPARATOR>}` | StringCombination, SEPARATOR> | SELF : never : never; /** * A type that merges all the input strings together and requires them sorted and interpreted in an ascending order * * NOTE: Intellisense may not display the correct order, but Typescript will enforce the expected order. * * Example: * 'a' | 'c' | 'b' w/ ',' -> 'a,b,c' */ export type StringConcatenationOrder = PopUnion extends infer SELF ? SELF extends string ? Exclude extends never ? `${SELF}` : `${StringConcatenationOrder, SEPARATOR>}${SEPARATOR}${SELF}` : never : never; /** * A type that merges all the input strings together using a separator. * * Example: * 'a' | 'b' | 'c' w/ ',' -> 'a,b,c' | 'a,c,b' | 'b,a,c' | etc... */ export type StringConcatenation = StringConcatenationMany; /** * Used to "approximate" larger concatenations. In reality, this just excludes the earlier types from being present in the middle. */ export type StringConcatenationApproximation = PopUnion extends infer SELF ? SELF extends string ? Exclude extends never ? `${SELF}` : `${StringConcatenationApproximation, SEPARATOR>}${SEPARATOR}${SELF}` | `${SELF}${SEPARATOR}${StringConcatenationApproximation, SEPARATOR>}` : never : never; /** * Creates the concatenations for the input. * * Total number of concatenations is equal to n!. * * The max number of strings allowed is 7. If there are more than 7 strings passed, this function will use StringConcatenationApproximation. */ export type StringConcatenationMany = PopUnion extends infer ONE ? ONE extends string ? PopUnion> extends infer TWO ? TWO extends string ? Exclude extends never ? StringConcatinateTwo : PopUnion> extends infer THREE ? THREE extends string ? Exclude extends never ? StringConcatinateThree : PopUnion> extends infer FOUR ? FOUR extends string ? Exclude extends never ? StringConcatinateFour : PopUnion> extends infer FIVE ? FIVE extends string ? Exclude extends never ? StringConcatinateFive : PopUnion> extends infer SIX ? SIX extends string ? Exclude extends never ? StringConcatinateSix : PopUnion> extends infer SEVEN ? SEVEN extends string ? Exclude extends never ? StringConcatinateSeven : PopUnion> extends infer EIGHT ? EIGHT extends string ? StringConcatenationApproximation : never : StringConcatinateSeven : never : StringConcatinateSix : never : StringConcatinateFive : never : StringConcatinateFour : never : StringConcatinateThree : StringConcatinateTwo : StringConcatinateTwo : never : ONE : never : never; export type StringConcatinateTwo = `${LEFT}${SEPARATOR}${SELF}` | `${SELF}${SEPARATOR}${LEFT}`; export type StringConcatinateThree = `${LEFT}${SEPARATOR}${SELF}${SEPARATOR}${RIGHT}` | `${LEFT}${SEPARATOR}${RIGHT}${SEPARATOR}${SELF}` | `${SELF}${SEPARATOR}${RIGHT}${SEPARATOR}${LEFT}` | `${SELF}${SEPARATOR}${LEFT}${SEPARATOR}${RIGHT}` | `${RIGHT}${SEPARATOR}${LEFT}${SEPARATOR}${SELF}` | `${RIGHT}${SEPARATOR}${SELF}${SEPARATOR}${LEFT}`; export type StringConcatinateFour = `${StringConcatinateThree}${SEPARATOR}${FOUR}` | `${StringConcatinateThree}${SEPARATOR}${ONE}` | `${StringConcatinateThree}${SEPARATOR}${TWO}` | `${StringConcatinateThree}${SEPARATOR}${THREE}`; export type StringConcatinateFive = `${StringConcatinateFour}${SEPARATOR}${FIVE}` | `${StringConcatinateFour}${SEPARATOR}${ONE}` | `${StringConcatinateFour}${SEPARATOR}${TWO}` | `${StringConcatinateFour}${SEPARATOR}${THREE}` | `${StringConcatinateFour}${SEPARATOR}${FOUR}`; export type StringConcatinateSix = `${StringConcatinateFive}${SEPARATOR}${SIX}` | `${StringConcatinateFive}${SEPARATOR}${ONE}` | `${StringConcatinateFive}${SEPARATOR}${TWO}` | `${StringConcatinateFive}${SEPARATOR}${THREE}` | `${StringConcatinateFive}${SEPARATOR}${FOUR}` | `${StringConcatinateFive}${SEPARATOR}${FIVE}`; export type StringConcatinateSeven = `${StringConcatinateSix}${SEPARATOR}${SIX}` | `${StringConcatinateSix}${SEPARATOR}${ONE}` | `${StringConcatinateSix}${SEPARATOR}${TWO}` | `${StringConcatinateSix}${SEPARATOR}${THREE}` | `${StringConcatinateSix}${SEPARATOR}${FOUR}` | `${StringConcatinateSix}${SEPARATOR}${FIVE}`; export type IsSingleCharacter = PopUnion extends infer SELF ? (Exclude extends never ? S : never) : never; export type HasTwoOrMoreCharacters = PopUnion extends infer FIRST ? FIRST extends string ? PopUnion> extends infer SECOND ? SECOND extends string ? S : never : never : never : never; export type HasThreeCharacters = PopUnion extends infer FIRST ? FIRST extends string ? PopUnion> extends infer SECOND ? SECOND extends string ? PopUnion> extends infer THIRD ? THIRD extends string ? Exclude extends never ? S : never : never : never : never : never : never : never; export type HasThreeOrMoreCharacters = PopUnion extends infer FIRST ? FIRST extends string ? PopUnion> extends infer SECOND ? SECOND extends string ? PopUnion> extends infer THIRD ? THIRD extends string ? S : never : never : never : never : never : never;