import type {Primitive} from './primitive'; import type {Simplify} from './simplify'; import type {Trim} from './trim'; /** Infer the length of the given array ``. @link https://itnext.io/implementing-arithmetic-within-typescripts-type-system-a1ef140a6f6f */ type TupleLength = T extends {readonly length: infer L} ? L : never; /** Create a tuple type of the given length ``. @link https://itnext.io/implementing-arithmetic-within-typescripts-type-system-a1ef140a6f6f */ type BuildTuple = T extends {readonly length: L} ? T : BuildTuple; /** Create a tuple of length `A` and a tuple composed of two other tuples, the inferred tuple `U` and a tuple of length `B`, then extracts the length of tuple `U`. @link https://itnext.io/implementing-arithmetic-within-typescripts-type-system-a1ef140a6f6f */ export type Subtract = BuildTuple extends [...(infer U), ...BuildTuple] ? TupleLength : never; /** Matches any primitive, `Date`, or `RegExp` value. */ export type BuiltIns = Primitive | Date | RegExp; /** Gets keys from a type. Similar to `keyof` but this one also works for union types. The reason a simple `keyof Union` does not work is because `keyof` always returns the accessible keys of a type. In the case of a union, that will only be the common keys. @link https://stackoverflow.com/a/49402091 */ export type KeysOfUnion = T extends T ? keyof T : never; export type UpperCaseCharacters = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z'; export type StringDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'; export type Whitespace = | '\u{9}' // '\t' | '\u{A}' // '\n' | '\u{B}' // '\v' | '\u{C}' // '\f' | '\u{D}' // '\r' | '\u{20}' // ' ' | '\u{85}' | '\u{A0}' | '\u{1680}' | '\u{2000}' | '\u{2001}' | '\u{2002}' | '\u{2003}' | '\u{2004}' | '\u{2005}' | '\u{2006}' | '\u{2007}' | '\u{2008}' | '\u{2009}' | '\u{200A}' | '\u{2028}' | '\u{2029}' | '\u{202F}' | '\u{205F}' | '\u{3000}' | '\u{FEFF}'; export type WordSeparators = '-' | '_' | Whitespace; /** Matches any unknown record. */ export type UnknownRecord = Record; /** Matches any unknown array or tuple. */ export type UnknownArrayOrTuple = readonly [...unknown[]]; /** Matches any non empty tuple. */ export type NonEmptyTuple = readonly [unknown, ...unknown[]]; /** Returns a boolean for whether the two given types extends the base type. */ export type IsBothExtends = FirstType extends BaseType ? SecondType extends BaseType ? true : false : false; /** Extracts the type of the first element of an array or tuple. */ export type FirstArrayElement = TArray extends readonly [infer THead, ...unknown[]] ? THead : never; /** Extracts the type of an array or tuple minus the first element. */ export type ArrayTail = TArray extends readonly [unknown, ...infer TTail] ? TTail : []; /** Extract the element of an array that also works for array union. Returns `never` if T is not an array. It creates a type-safe way to access the element type of `unknown` type. */ export type ArrayElement = T extends readonly unknown[] ? T[0] : never; /** Extract the object field type if T is an object and K is a key of T, return `never` otherwise. It creates a type-safe way to access the member type of `unknown` type. */ export type ObjectValue = K extends keyof T ? T[K] : never; /** Returns a boolean for whether the string is lowercased. */ export type IsLowerCase = T extends Lowercase ? true : false; /** Returns a boolean for whether the string is uppercased. */ export type IsUpperCase = T extends Uppercase ? true : false; /** Returns a boolean for whether a string is whitespace. */ export type IsWhitespace = T extends Whitespace ? true : T extends `${Whitespace}${infer Rest}` ? IsWhitespace : false; /** Returns a boolean for whether the string is numeric. This type is a workaround for [Microsoft/TypeScript#46109](https://github.com/microsoft/TypeScript/issues/46109#issuecomment-930307987). */ export type IsNumeric = T extends `${number}` ? Trim extends T ? true : false : false; /** Returns a boolean for whether the the type is `any`. @link https://stackoverflow.com/a/49928360/1490091 */ export type IsAny = 0 extends 1 & T ? true : false; /** Returns a boolean for whether the the type is `never`. */ export type IsNever = [T] extends [never] ? true : false; /** Returns a boolean for whether the the type is `unknown`. */ export type IsUnknown = IsNever extends false ? T extends unknown ? unknown extends T ? IsAny extends false ? true : false : false : false : false; /** For an object T, if it has any properties that are a union with `undefined`, make those into optional properties instead. @example ``` type User = { firstName: string; lastName: string | undefined; }; type OptionalizedUser = UndefinedToOptional; //=> { // firstName: string; // lastName?: string; // } ``` */ export type UndefinedToOptional = Simplify< { // Property is not a union with `undefined`, keep it as-is. [Key in keyof Pick>]: T[Key]; } & { // Property _is_ a union with defined value. Set as optional (via `?`) and remove `undefined` from the union. [Key in keyof Pick>]?: Exclude; } >; // Returns `never` if the key or property is not jsonable without testing whether the property is required or optional otherwise return the key. type BaseKeyFilter = Key extends symbol ? never : Type[Key] extends symbol ? never : [(...arguments_: any[]) => any] extends [Type[Key]] ? never : Key; /** Returns the required keys. */ type FilterDefinedKeys = Exclude< { [Key in keyof T]: IsAny extends true ? Key : undefined extends T[Key] ? never : T[Key] extends undefined ? never : BaseKeyFilter; }[keyof T], undefined >; /** Returns the optional keys. */ type FilterOptionalKeys = Exclude< { [Key in keyof T]: IsAny extends true ? never : undefined extends T[Key] ? T[Key] extends undefined ? never : BaseKeyFilter : never; }[keyof T], undefined >; /** Test if the given function has multiple call signatures. Needed to handle the case of a single call signature with properties. Multiple call signatures cannot currently be supported due to a TypeScript limitation. @see https://github.com/microsoft/TypeScript/issues/29732 */ export type HasMultipleCallSignatures unknown> = T extends {(...arguments: infer A): unknown; (...arguments: any[]): unknown} ? unknown[] extends A ? false : true : false;