import type {Primitive} from './primitive'; import type {Simplify} from './simplify'; import type {Trim} from './trim'; import type {IsAny} from './is-any'; import type {NegativeInfinity, PositiveInfinity} from './numeric'; import type {GreaterThan} from './greater-than'; import type {LessThan} from './less-than'; import type {IsLiteral} from './is-literal'; import type {UnknownRecord} from './unknown-record'; import type {IsNever} from './is-never'; import type {UnknownArray} from './unknown-array'; import type {IsEqual} from './is-equal'; // TODO: Remove for v5. export type {UnknownRecord} from './unknown-record'; /** Infer the length of the given array ``. @link https://itnext.io/implementing-arithmetic-within-typescripts-type-system-a1ef140a6f6f */ type ArrayLength = T extends {readonly length: infer L} ? L : never; /** Infer the length of the given tuple ``. Returns `never` if the given type is an non-fixed-length array like `Array`. @example ``` type Tuple = TupleLength<[string, number, boolean]>; //=> 3 type Array = TupleLength; //=> never // Supports union types. type Union = TupleLength<[] | [1, 2, 3] | Array>; //=> 1 | 3 ``` */ export type TupleLength = // `extends unknown` is used to convert `T` (if `T` is a union type) to // a [distributive conditionaltype](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types)) T extends unknown ? number extends T['length'] ? never // Return never if the given type is an non-flexed-length array like `Array` : T['length'] : never; // Should never happen /** Create a tuple type of the given length `` and fill it with the given type ``. If `` is not provided, it will default to `unknown`. @link https://itnext.io/implementing-arithmetic-within-typescripts-type-system-a1ef140a6f6f */ export type BuildTuple = T['length'] extends L ? T : BuildTuple; /** Create an object type with the given key `` and value ``. It will copy the prefix and optional status of the same key from the given object `CopiedFrom` into the result. @example ``` type A = BuildObject<'a', string>; //=> {a: string} // Copy `readonly` and `?` from the key `a` of `{readonly a?: any}` type B = BuildObject<'a', string, {readonly a?: any}>; //=> {readonly a?: string} ``` */ export type BuildObject = Key extends keyof CopiedFrom ? Pick<{[_ in keyof CopiedFrom]: Value}, Key> : Key extends `${infer NumberKey extends number}` ? NumberKey extends keyof CopiedFrom ? Pick<{[_ in keyof CopiedFrom]: Value}, NumberKey> : {[_ in Key]: Value} : {[_ in Key]: Value}; /** Return a string representation of the given string or number. Note: This type is not the return type of the `.toString()` function. */ export type ToString = T extends string | number ? `${T}` : never; /** Matches any primitive, `void`, `Date`, or `RegExp` value. */ export type BuiltIns = Primitive | void | Date | RegExp; /** Matches non-recursive types. */ export type NonRecursiveType = BuiltIns | Function | (new (...arguments_: any[]) => unknown); /** Returns a boolean for whether the given type is a plain key-value object. */ export type IsPlainObject = T extends NonRecursiveType | UnknownArray | ReadonlyMap | ReadonlySet ? false : T extends object ? true : false; /** Converts a numeric string to a number. @example ``` type PositiveInt = StringToNumber<'1234'>; //=> 1234 type NegativeInt = StringToNumber<'-1234'>; //=> -1234 type PositiveFloat = StringToNumber<'1234.56'>; //=> 1234.56 type NegativeFloat = StringToNumber<'-1234.56'>; //=> -1234.56 type PositiveInfinity = StringToNumber<'Infinity'>; //=> Infinity type NegativeInfinity = StringToNumber<'-Infinity'>; //=> -Infinity ``` @category String @category Numeric @category Template literal */ export type StringToNumber = S extends `${infer N extends number}` ? N : S extends 'Infinity' ? PositiveInfinity : S extends '-Infinity' ? NegativeInfinity : never; /** Returns a boolean for whether the given string `S` starts with the given string `SearchString`. @example ``` StartsWith<'abcde', 'abc'>; //=> true StartsWith<'abcde', 'bc'>; //=> false StartsWith; //=> never StartsWith<'abcde', string>; //=> never ``` @category String @category Template literal */ export type StartsWith = string extends S | SearchString ? never : S extends `${SearchString}${infer T}` ? true : false; /** Returns the length of the given string. @example ``` StringLength<'abcde'>; //=> 5 StringLength; //=> never ``` @category String @category Template literal */ export type StringLength = string extends S ? never : StringToArray['length']; /** Returns an array of the characters of the string. @example ``` StringToArray<'abcde'>; //=> ['a', 'b', 'c', 'd', 'e'] StringToArray; //=> never ``` @category String */ export type StringToArray = string extends S ? never : S extends `${infer F}${infer R}` ? StringToArray : Result; 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 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] : ToString extends keyof T ? T[ToString] : K extends `${infer NumberK extends number}` ? NumberK extends keyof T ? T[NumberK] : never : 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; /** 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 /* To prevent a problem where an object with only a `name` property is incorrectly treated as assignable to a function, we first check if the property is a record. This check is necessary, because without it, if we don't verify whether the property is a record, an object with a type of `{name: any}` would return `never` due to its potential assignability to a function. See: https://github.com/sindresorhus/type-fest/issues/657 */ : Type[Key] extends Record ? Key : [(...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_: infer B): unknown} ? B extends A ? A extends B ? false : true : true : false; /** Returns a boolean for whether the given `boolean` is not `false`. */ export type IsNotFalse = [T] extends [false] ? false : true; /** Disallows any of the given keys. */ export type RequireNone = Partial>; /** Returns a boolean for whether the given type is primitive value or primitive type. @example ``` IsPrimitive<'string'> //=> true IsPrimitive //=> true IsPrimitive //=> false ``` */ export type IsPrimitive = [T] extends [Primitive] ? true : false; /** Returns a boolean for whether A is false. @example ``` Not; //=> false Not; //=> true ``` */ export type Not = A extends true ? false : A extends false ? true : never; /** Returns the maximum value from a tuple of integers. Note: - Float numbers are not supported. @example ``` ArrayMax<[1, 2, 5, 3]>; //=> 5 ArrayMax<[1, 2, 5, 3, 99, -1]>; //=> 99 ``` */ export type ArrayMax = number extends A[number] ? never : A extends [infer F extends number, ...infer R extends number[]] ? GreaterThan extends true ? ArrayMax : ArrayMax : Result; /** Returns the minimum value from a tuple of integers. Note: - Float numbers are not supported. @example ``` ArrayMin<[1, 2, 5, 3]>; //=> 1 ArrayMin<[1, 2, 5, 3, -5]>; //=> -5 ``` */ export type ArrayMin = number extends A[number] ? never : A extends [infer F extends number, ...infer R extends number[]] ? LessThan extends true ? ArrayMin : ArrayMin : Result; /** Returns the absolute value of a given value. @example ``` NumberAbsolute<-1>; //=> 1 NumberAbsolute<1>; //=> 1 NumberAbsolute //=> PositiveInfinity ``` */ export type NumberAbsolute = `${N}` extends `-${infer StringPositiveN}` ? StringToNumber : N; /** Returns a boolean for whether `A` represents a number greater than `B`, where `A` and `B` are both numeric strings and have the same length. @example ``` SameLengthPositiveNumericStringGt<'50', '10'>; //=> true SameLengthPositiveNumericStringGt<'10', '10'>; //=> false ``` */ type SameLengthPositiveNumericStringGt = A extends `${infer FirstA}${infer RestA}` ? B extends `${infer FirstB}${infer RestB}` ? FirstA extends FirstB ? SameLengthPositiveNumericStringGt : PositiveNumericCharacterGt : never : false; type NumericString = '0123456789'; /** Returns a boolean for whether `A` is greater than `B`, where `A` and `B` are both positive numeric strings. @example ``` PositiveNumericStringGt<'500', '1'>; //=> true PositiveNumericStringGt<'1', '1'>; //=> false PositiveNumericStringGt<'1', '500'>; //=> false ``` */ export type PositiveNumericStringGt = A extends B ? false : [BuildTuple, 0>, BuildTuple, 0>] extends infer R extends [readonly unknown[], readonly unknown[]] ? R[0] extends [...R[1], ...infer Remain extends readonly unknown[]] ? 0 extends Remain['length'] ? SameLengthPositiveNumericStringGt : true : false : never; /** Returns a boolean for whether `A` represents a number greater than `B`, where `A` and `B` are both positive numeric characters. @example ``` PositiveNumericCharacterGt<'5', '1'>; //=> true PositiveNumericCharacterGt<'1', '1'>; //=> false ``` */ type PositiveNumericCharacterGt = NumericString extends `${infer HeadA}${A}${infer TailA}` ? NumericString extends `${infer HeadB}${B}${infer TailB}` ? HeadA extends `${HeadB}${infer _}${infer __}` ? true : false : never : never; /** Utility type to retrieve only literal keys from type. */ export type LiteralKeyOf = keyof {[K in keyof T as IsLiteral extends true ? K : never]-?: never}; /** Returns the static, fixed-length portion of the given array, excluding variable-length parts. @example ``` type A = [string, number, boolean, ...string[]]; type B = StaticPartOfArray; //=> [string, number, boolean] ``` */ export type StaticPartOfArray = T extends unknown ? number extends T['length'] ? T extends readonly [infer U, ...infer V] ? StaticPartOfArray : Result : T : never; // Should never happen /** Returns the variable, non-fixed-length portion of the given array, excluding static-length parts. @example ``` type A = [string, number, boolean, ...string[]]; type B = VariablePartOfArray; //=> string[] ``` */ export type VariablePartOfArray = T extends unknown ? T extends readonly [...StaticPartOfArray, ...infer U] ? U : [] : never; // Should never happen /** Returns the minimum number in the given union of numbers. Note: Just supports numbers from 0 to 999. @example ``` type A = UnionMin<3 | 1 | 2>; //=> 1 ``` */ export type UnionMin = InternalUnionMin; /** The actual implementation of `UnionMin`. It's private because it has some arguments that don't need to be exposed. */ type InternalUnionMin = T['length'] extends N ? T['length'] : InternalUnionMin; /** Returns the maximum number in the given union of numbers. Note: Just supports numbers from 0 to 999. @example ``` type A = UnionMax<1 | 3 | 2>; //=> 3 ``` */ export type UnionMax = InternalUnionMax; /** The actual implementation of `UnionMax`. It's private because it has some arguments that don't need to be exposed. */ type InternalUnionMax = IsNever extends true ? T['length'] : T['length'] extends N ? InternalUnionMax, T> : InternalUnionMax; /** Returns a boolean for whether the given type is a union type. @example ``` type A = IsUnion; //=> true type B = IsUnion; //=> false ``` */ export type IsUnion = InternalIsUnion; /** The actual implementation of `IsUnion`. */ type InternalIsUnion = ( // @link https://ghaiklor.github.io/type-challenges-solutions/en/medium-isunion.html IsNever extends true ? false : T extends any ? [U] extends [T] ? false : true : never ) extends infer Result // In some cases `Result` will return `false | true` which is `boolean`, // that means `T` has at least two types and it's a union type, // so we will return `true` instead of `boolean`. ? boolean extends Result ? true : Result : never; // Should never happen /** Set the given array to readonly if `IsReadonly` is `true`, otherwise set the given array to normal, then return the result. @example ``` type ReadonlyArray = readonly string[]; type NormalArray = string[]; type ReadonlyResult = SetArrayAccess; //=> readonly string[] type NormalResult = SetArrayAccess; //=> string[] ``` */ export type SetArrayAccess = T extends readonly [...infer U] ? IsReadonly extends true ? readonly [...U] : [...U] : T; /** Returns whether the given array `T` is readonly. */ export type IsArrayReadonly = T extends unknown[] ? false : true; /** Get the exact version of the given `Key` in the given object `T`. Use-case: You known that a number key (e.g. 10) is in an object, but you don't know how it is defined in the object, as a string or as a number (e.g. 10 or '10'). You can use this type to get the exact version of the key. See the example. @example ``` type Object = { 0: number; '1': string; }; type Key1 = ExactKey; //=> 0 type Key2 = ExactKey; //=> 0 type Key3 = ExactKey; //=> '1' type Key4 = ExactKey; //=> '1' ``` @category Object */ export type ExactKey = Key extends keyof T ? Key : ToString extends keyof T ? ToString : Key extends `${infer NumberKey extends number}` ? NumberKey extends keyof T ? NumberKey : never : never;