typelab / utils
Handy set of TypeScript utility types for transforming and working with other types. Includes helpers for arrays, objects, unions, functions, and common type operations like extracting, excluding, mapping, and parsing.
| Type Alias | Description |
|---|---|
|
Extracts the Example type Length = ArrayLength<[1, 2, 3]>; // 3
type Length2 = ArrayLength<string[]>; // number
type Never = ArrayLength<any>; // never |
|
|
Extracts the elements of an Example type Elements = ArrayElements<[string, number]>; // string | number
type Never = ArrayElements<any>; // never |
|
|
Alias for `ArrayElements`. Extracts the values of an Example type Values = ArrayValues<[string, number]>; // string | number
type Never = ArrayValues<any>; // never |
|
|
Extracts the index keys of an
Example // 0 | 1 | 2
type Result1 = ArrayIndexes<[string, number, boolean]>;
// 0 | 1 | 2 | "0" | "1" | "2"
type Result2 = ArrayIndexes<[string, number, boolean], true>;
// number
type Result3 = ArrayIndexes<string[]>;
// never
type Never = ArrayIndexes<any>; |
|
|
Extracts the type of an element at a specific index from an Example type ElementAt = ArrayAt<[string, number, boolean], 1>; // number
type Undefined = ArrayAt<[string, number, boolean], 3>; // undefined
type Never = ArrayAt<any, 1>; // never |
|
|
Extracts the type of the first element of an Example // string
type FirstElement = ArrayFirst<[string, number, boolean]>;
// string | number | boolean
type AllElements = ArrayFirst<(string | number | boolean)[]>;
// never
type Never = ArrayFirst<any>; |
|
|
Extracts the type of the last element of an Example // boolean
type LastElement = ArrayLast<[string, number, boolean]>;
// string | number | boolean
type AllElements = ArrayLast<(string | number | boolean)[]>;
// never
type Never = ArrayLast<any>; |
|
|
Concatenates two Template The first Template The second Example // [string, number, boolean, object]
type Concatenated1 = ArrayConcat<[string, number], [boolean, object]>;
// [...string[], boolean, object]
type Concatenated2 = ArrayConcat<string[], [boolean, object]>;
// [string, number, ...object[]]
type Concatenated3 = ArrayConcat<[string, number], object[]>;
// [string, number, any]
type Concatenated4 = ArrayConcat<[string, number], any>;
// never
type Never = ArrayConcat<any, [string, number]>; |
|
|
Adds a new element to the end of a Example type Pushed = ArrayPush<[string, number], boolean>; // [string, number, boolean]
type Same = ArrayPush<[string, number], never>; // [string, number]
type Never1 = ArrayPush<readonly [string, number], string> // never
type Never2 = ArrayPush<any, string> // never |
|
|
Removes the last element from an Example type Popped = ArrayPop<[string, number]>; // [string]
type Same = ArrayPop<(string | number)[]>; // (string | number)[]
type Never1 = ArrayPop<readonly [string, number]>; // never
type Never2 = ArrayPop<any>; // never |
|
|
Adds a new element to the beginning of an Example // [boolean, string, number]
type Unshifted = ArrayUnshift<[string, number], boolean>;
// [string, number]
type Same = ArrayUnshift<[string, number], never>;
// never
type Never1 = ArrayPush<readonly [string, number], string>;
// never
type Never2 = ArrayPush<any, string>; |
|
|
Removes the first element from an Example type Shifted = ArrayShift<[string, number]>; // [number]
type Same = ArrayShift<(string | number)[]>; // (string | number)[]
type Never1 = ArrayShift<readonly [string, number]>; // never
type Never2 = ArrayShift<any>; // never |
|
|
Type that flattens a nested Example // [0, 1, 2, 3, 4, 5, 6, 7]
type Flattened1 = ArrayFlat<[0, 1, [2, 3, [4, 5, [6, 7[]]]]]>;
// (0 | 1 | 2 | 3 | 4 | 5 | 6 | 7)[]
type Flattened2 = ArrayFlat<(0 | 1 | [2] | [3] | [[4]] | [[5]] | [[[6]]] | [[[7[]]]])[]>;
// never
type Never = ArrayFlat<any>; |
|
|
Takes the first If Example type Result1 = ArrayTake<[1, 2, 3, 4], 2>; // [1, 2]
type Result2 = ArrayTake<[1, 2, 3, 4], -2>; // [3, 4]
type Result3 = ArrayTake<[1, 2, 3, 4], 5>; // [1, 2, 3, 4]
type Result4 = ArrayTake<[1, 2, 3, 4]>; // [1, 2, 3, 4]
type Never1 = ArrayTake<[1, 2, 3, 4], any>; // never
type Never2 = ArrayTake<[1, 2, 3, 4], never>; // never
type Never3 = ArrayTake<any, 1>; // never |
|
|
Skips the first If Example type Result1 = ArraySkip<[1, 2, 3, 4], 2>; // [3, 4]
type Result2 = ArraySkip<[1, 2, 3, 4], -2>; // [1, 2]
type Result3 = ArraySkip<[1, 2, 3, 4], 5>; // []
type Result4 = ArraySkip<[1, 2, 3, 4]>; // [1, 2, 3, 4]
type Never1 = ArraySkip<[1, 2, 3, 4], any>; // never
type Never2 = ArraySkip<any, 1>; // never |
|
|
Extended TypeScript `Required` to handle Example type Result1 = ArrayRequired<[string?, string?]>; // [string, string]
type Result2 = ArrayRequired<[string?, string?], 0>; // [string, string?]
type Result3 = ArrayRequired<[string?, string?], 0, true>; // [string | undefined, string?]
type Never1 = ArrayRequired<[string?, string?], any>; // never
type Never2 = ArrayRequired<any, 1>; // never |
|
|
Extended TypeScript `Partial` to handle Example type Result1 = ArrayPartial<[string, string]>; // [string?, string?]
type Result2 = ArrayPartial<[string, string], 1>; // [string, string?]
type Never1 = ArrayPartial<[string, string], any>; // never
type Never2 = ArrayPartial<any, 1>; // never |
|
|
Get the required indexes from Example // 0 | 1
type Result1 = ArrayRequiredIndexes<[string, string, string?]>;
// 0 | 1 | "0" | "1"
type Result2 = ArrayRequiredIndexes<[string, string, string?], true>;
// number
type Result3 = ArrayRequiredIndexes<(string | undefined)[]>;
// never
type Never1 = ArrayRequiredIndexes<[string?, string?, string?]>;
// never
type Never2 = ArrayRequiredIndexes<any>; |
|
|
Get the optional indexes from Example // 1 | 2
type Result1 = ArrayOptionalIndexes<[string, string?, string?]>;
// 1 | 2 | "1" | "2"
type Result2 = ArrayOptionalIndexes<[string, string?, string?], true>;
// number
type Result3 = ArrayOptionalIndexes<(string | undefined)[]>;
// never
type Never1 = ArrayOptionalIndexes<[string, string, string]>;
// never
type Never2 = ArrayOptionalIndexes<any>; |
|
|
Get the required elements from Example // 0 | 1
type Result1 = ArrayRequiredElements<[0, 1, 2?]>;
// string | undefined
type Result2 = ArrayRequiredElements<(string | undefined)[]>;
// never
type Never1 = ArrayRequiredElements<[0?, 1?, 2?]>;
// never
type Never2 = ArrayRequiredElements<any>; |
|
|
Get the optional elements from Example // 1 | 2 | undefined
type Result1 = ArrayOptionalElements<[0, 1?, 2?]>;
// string | undefined
type Result2 = ArrayOptionalElements<(string | undefined)[]>;
// never
type Never1 = ArrayOptionalElements<[0, 1, 2]>;
// never
type Never2 = ArrayOptionalElements<any>; |
|
|
Alias for `ArrayRequiredElements`. |
|
|
Alias for `ArrayOptionalElements`. |
|
|
Omit the required elements from Example // [string?, string?]
type Result1 = ArrayOmitRequired<[string, string, string?, string?]>;
// [unknown?, string?, string?]
type Result2 = ArrayOmitRequired<[string, string?, string?], false>;
// never
type Never = ArrayOmitRequired<any>; |
|
|
Omit the optional elements from Example // [string, string]
type Result = ArrayOmitOptional<[string, string, string?]>;
// never
type Never = ArrayOmitOptional<any>; |
|
|
Converts an
Example // { 0: string, 1: number }
type Result1 = ArrayToObject<[string, number]>;
// { [x: number]: string }
type Result2 = ArrayToObject<string[]>;
// never
type Never = ArrayToObject<any>; |
|
|
Assign the elements of It's like ObjectAssign but for
Example // [0, 1, 2]
type Result1 = ArrayAssign<[1, 2], [0, 1, 2]>;
// (string | number)[]
type Result2 = ArrayAssign<string[], number[]>;
// readonly [1, 2]
type Result3 = ArrayAssign<readonly [1, 2], [0, 1, 2]>; |
|
|
Overwrite elements of This type will overwrite all nested Example type Arr1 = [string, [string, string]];
type Arr2 = [number, [number], number];
// [number, [number], number]
type Shallow = ArrayOverwrite<Arr1, Arr2, 'shallow'>;
// [number, [number, string], number]
type Deep = ArrayOverwrite<Arr1, Arr2, 'deep'>; |
|
|
Merges elements of This type will merge all nested Example type Arr1 = [string, [string, string]];
type Arr2 = [number, [number], number];
// [string | number, [number] | [string, string], number]
type Shallow = ArrayMerge<Arr1, Arr2, 'shallow'>;
// [string | number, [string | number, string], number]
type Deep = ArrayMerge<Arr1, Arr2, 'deep'>; |
|
|
Unions the elements of an This type will unionize all nested Example // [string | number, number | [number, boolean]]
type Shallow = ArrayUnionize<[string, [number, boolean]], number, 'shallow'>;
// [string | number, [number, number | boolean]]
type Deep = ArrayUnionize<[string, [number, boolean]], number, 'deep'>; |
|
|
Create a branded version of a base type. Example type UserId = Brand<string, 'UserId'>; // string & { __brand: "UserId" }
type OrderId = Brand<string, 'OrderId'>; // string & { __brand: "OrderId" }
type IsEqual = [UserId, OrderId] extends [OrderId, UserId] ? true : false; // false |
|
|
Recursively applies a deep transformation to each property of Example type ComplexObj = Required<{ b?: string } & { c?: string }> & { d: string };
type Obj = { a: string; nested: ComplexObj };
// Detail is { a: string; nested: { b: string; c: string; d: string }; }
type Detail = Detailed<Obj>; |
|
|
Exclude Example type NonNullishType = ExcludeNullish<string | null | undefined>; // string |
|
|
Exclude Example type NonNullType = ExcludeNull<string | null>; // string |
|
|
Exclude Example type NonUndefinedType = ExcludeUndefined<string | undefined>; // string |
|
|
Extract the value type from an Example type Valid = ExtractArray<number[]>; // number
type Invalid = ExtractArray<Promise<number>> // never |
|
|
Extract the value type from a Example type Valid = ExtractPromise<Promise<number>>; // number
type Invalid = ExtractPromise<number>> // never |
|
|
Type that extracts the parameters from Example // [string, number]
type FunctionParams = ExtractParams<(a: string, b: number) => void>;
// [string, number]
type NewableParams = ExtractParams<new (a: string, b: number) => { a: string; b: string }>;
class MyClass { constructor(public a: string, public b: number) {}}
// [string, number]
type ClassParams = ExtractParams<typeof MyClass>; |
|
|
Type that extracts the return type from Example // string
type FunctionReturn = ExtractReturn<(a: string, b: number) => string>;
// { a: string; b: string }
type NewableReturn = ExtractReturn<new (a: string, b: number) => { a: string; b: string }>; |
|
|
Assign the parameter and return types of Use `ArrayAssign` for the parameter type and `ObjectAssign` for the return type.
Example // (param_0: number, param_1: string) => { a: number; b: string }
type Result = FunctionAssign<(...param: [string, string]) => { a: string; b: string }, (...param: [number]) => { a: number }> |
|
|
Alias for `FunctionAssign`. |
|
|
Overwrite the parameter and return types of Use `ArrayOverwrite` for the parameter type and `ObjectOverwrite` for the return type.
Example type Obj1 = { a: string; b: { a: string } };
type Obj2 = { a: number; b: { b: number } };
// (param_0: number, param_1: string) => { a: number; b: { b: number; }; }
type Shallow = FunctionOverwrite<(...param: [string, string]) => Obj1, (...param: [number]) => Obj2, 'shallow'>;
// (param_0: number, param_1: string) => { a: number; b: { a: string, b: number; }; }
type Deep = FunctionOverwrite<(...param: [string, string]) => Obj1, (...param: [number]) => Obj2, 'deep'>; |
|
|
Alias for `FunctionOverwrite`. |
|
|
Merges the parameter and return types of Use `ArrayMerge` for the parameter type and `ObjectMerge` for the return type.
Example type Obj1 = { a: string; b: { a: string } };
type Obj2 = { a: number; b: { b: number } };
// (param_0: string | number, param_1: string) => { a: string | number; b: { a: string; } | { b: number; }; }
type Shallow = FunctionMerge<(...param: [string, string]) => Obj1, (...param: [number]) => Obj2, 'shallow'>;
// (param_0: string | number, param_1: string) => { a: string | number; b: { a: string; b: number; }; }
type Deep = FunctionMerge<(...param: [string, string]) => Obj1, (...param: [number]) => Obj2, 'deep'>; |
|
|
Alias for `FunctionMerge`. |
|
|
Converts a If the Example // Callback-style function:
// (a: string) => Promise<string>
type Promisified = FunctionPromisify<(a: string, callback: (error: Error, result: string) => void) => void>;
// Regular function:
// (a: string) => Promise<string>
type PromisifiedFn = FunctionPromisify<(a: string) => string>; |
|
|
Alias for `FunctionPromisify`. |
|
|
Converts an Example // (a: string, callback: (error: unknown, result: string) => void) => void
type Callbackified = FunctionCallbackify<(a: string) => Promise<string>>; |
|
|
Alias for `FunctionCallbackify`. |
|
|
Extracts the keys of an Example // Keys is 'a' | 'b'
type Keys = KeyOf<{ a: string; b: number }>; |
|
|
Recursively applies a shallow transformation to each property of Simpler version of `Detailed` Example type Obj = Required<{ b?: string } & { c?: string }> & { d: string };
// Detail is { b: string; c: string; d: string }
type Detail = Mapped<Obj>; |
|
|
Increments a given Example type IncrementNumber = Increment<5>; // 6
type IncrementBigInt = Increment<10n>; // 11n
type IncrementNegative = Increment<-3.14>; // -2.14 |
|
|
Decrements a given Example type DecrementNumber = Decrement<5>; // 4
type DecrementBigInt = Decrement<10n>; // 9n
type DecrementNegative = Decrement<-3.14>; // -4.14 |
|
|
Extended TypeScript `Pick` to pick Example type Obj = { a: string; b: string };
// { a: string; }
type Picked = ObjectPick<Obj, 'a'>; |
|
|
Extended TypeScript `Required` to enforce specific properties as required. Example type Obj = { a?: string; b?: string };
// { a: string; b?: string }
type RequiredObj = ObjectRequired<Obj, 'a'>; |
|
|
Extended TypeScript `Partial` to make specific properties optional. Example type Obj = { a: string; b: string };
// { a?: string; b: string }
type PartialObj = ObjectPartial<Obj, 'a'>; |
|
|
Get the required keys from Example type Obj = { a: number; b: string | undefined; c?: boolean };
type RequiredKeys = ObjectRequiredKeys<Obj>; // "a" | "b" |
|
|
Get the optional keys from Example type Obj = { a: number; b: string | undefined; c?: boolean };
type OptionalKeys = ObjectOptionalKeys<Obj>; // "c" |
|
|
Get the optional properties from This type will lookup all nested objects (if Example type Obj = { a: string | undefined; b?: string; c?: { d: string; e?: string } };
// { b?: string; c?: { d: string; e?: string; }; }
type Shallow = ObjectOmitRequired<Obj, 'shallow'>;
// { b?: string; c?: { e?: string; }; }
type Deep = ObjectOmitRequired<Obj, 'deep'>; |
|
|
Get the required properties from This type will lookup all nested objects (if Example type Obj = { a: string | undefined; b?: string; c: { d: string, e?: string } };
// { a: string | undefined; c: { d: string; e?: string } }
type Shallow = ObjectOmitOptional<Obj, 'shallow'>;
// { a: string | undefined; c: { d: string; }}
type Deep = ObjectOmitOptional<Obj, 'deep'>; |
|
|
Extended TypeScript `Readonly` to enforce specific properties as readonly. Example type Obj = { a: string; b: string };
// { readonly a: string; b: string }
type ReadonlyObj = ObjectReadonly<Obj, 'a'>; |
|
|
Enforce specific properties as writable. Example type Obj = { readonly a: string; b: string };
// WritableObj is { a: string; b: string; }
type WritableObj = ObjectWritable<Obj, 'a'>; |
|
|
Get all of the paths from Example type Obj = { a: { b: number }; c: string };
type Paths = ObjectPath<Obj>; // "a" | "a.b" | "c" |
|
|
Get the type of a property based on a given path. Example type Obj = { a: { b: number }; c: string };
type ValueType = ObjectPathValue<Obj, 'a.b'>; // number |
|
|
Converts an
Example type Obj1 = { 0: string; 1: number; 2: boolean };
// [string, number, boolean]
type TupleType1 = ObjectToTuple<Obj1>;
type Obj2 = { a: 'a'; b: 'b'; c: 'c' };
// ['a', 'b, 'c']
type TupleType2 = ObjectToTuple<Obj2, true>; |
|
|
Assign properties of The result of type follows the actual result of Example // { a: string; b: string; c: boolean }
type Assign1 = ObjectAssign<{ a: string; b: number }, { b: string; c: boolean }>;
// { a: string; 0: string }
type Assign2 = ObjectAssign<{ a: string }, [string]>;
// { [x: number]: string, a: string }
type Assign3 = ObjectAssign<{ a: string }, string[]>;
// [number, number]
type Assign4 = ObjectAssign<[string], [number, number]>;
// (string | number)[]
type Assign5 = ObjectAssign<string[], [number, number]>;
// (string | number)[]
type Assign6 = ObjectAssign<string[], number[]>;
// [number, string]
type Assign7 = ObjectAssign<[string], { 0: number; 1: string }>;
// (string | number)[]
type Assign8 = ObjectAssign<[number], 'str'>;
// { [x: number]: string, a: string }
type Assign9 = ObjectAssign<{a: string}, 'str'>; |
|
|
Overwrite properties of This type will overwrite all nested Example type Obj1 = { a: string; b: string; c: { a: string } };
type Obj2 = { b: number; c: { b: number }; d: number };
// { a: string; b: number; c: { b: number; }; d: number }
type Shallow = ObjectOverwrite<Obj1, Obj2, 'shallow'>;
// { a: string; b: number; c: { a: string; b: number; }; d: number }
type Deep = ObjectOverwrite<Obj1, Obj2, 'deep'>; |
|
|
Merges properties of This type will merge all nested Example type Obj1 = { a: string; b: string; c: { a: string; } };
type Obj2 = { b: number; c: { a: number; b: number }; d: number };
// { a: string; b: string | number; c: { a: string; } | { a: number; b: number }; d: number }
type Shallow = ObjectMerge<Obj1, Obj2, 'shallow'>;
// { a: string; b: string | number; c: { a: string | number; b: number; }; d: number }
type Deep = ObjectMerge<Obj1, Obj2, 'deep'>; |
|
|
Unions the properties of an This type will unionize all nested Example // { a: string | number; b: number | { a: string; }; }
type Shallow = ObjectUnionize<{ a: string; b: { a: string } }, number, 'shallow'>;
// { a: string | number; b: { a: string | number; }; }
type Deep = ObjectUnionize<{ a: string; b: { a: string } }, number, 'deep'>; |
|
|
Parses a Example type Int = ParseInt<'11'>; // 11 |
|
|
Parses a Example type Int = ParseIntNegative<'11'>; // -11 |
|
|
Parses a Example type Int = ParseIntPositive<'-11'>; // 11 |
|
|
Parses a Example type Float = ParseFloat<'11.1'>; // 11.1 |
|
|
Parses a Example type Float = ParseFloatNegative<'11.1'>; // -11.1 |
|
|
Parses a Example type Float = ParseFloatPositive<'-11.1'>; // 11.1 |
|
|
Parses a Example type Bigi = ParseBigInt<'11n'>; // 11n |
|
|
Parses a Example type Bigi = ParseBigIntNegative<'11'>; // -11n |
|
|
Parses a Example type Bigi = ParseBigIntPositive<'-11'>; // 11n |
|
|
Converts a type to a Example type Stringified = ParseString<11>; // '11' |
|
|
Converts a type to a Example type True1 = ParseBoolean<'true'>; // true
type True2 = ParseBoolean<1>; // true
type False1 = ParseBoolean<'false'>; // false
type False2 = ParseBoolean<0>; // false |
|
|
Converts a type to an Example type Obj = ParseObject<true>; // { valueOf: () => boolean } |
|
|
Gets the type of a property Example type User = { name: string };
type Valid = PropValue<User, 'name'>; // string
type Invalid = PropValue<User, 'email'>; // never |
|
|
Toggle the values of a Example type Toggled1 = Toggle<true>; // false
type Toggled2 = Toggle<false>; // true |
|
|
Converts a union type to an intersection type. Example // { a: number } & { b: string }
type Intersect = UnionToIntersection<{ a: number } | { b: string }>; |
|
|
Extracts the last type from a union type. Example // 'c'
type Last = UnionLast<'a' | 'b' | 'c'>; |
|
|
Removes the last type from a union. Example // 'a' | 'b'
type Popped = UnionPop<'a' | 'b' | 'c'>; |
|
|
Get the intersection of two union types, combining only the types that exist in both unions. Example // 'b'
type Result = UnionIntersection<'a' | 'b', 'b' | 'c'>; |
|
|
Creates a union of types that are exclusive to each other. Example // 'a' | 'c'
type Exclusive = UnionExclusive<'a' | 'b', 'b' | 'c'>; |
|
|
Converts a union type to a Example // ['a', 'b', 'c']
type Tupl = UnionToTuple<'a' | 'b' | 'c'>; |
|
|
Extracts the values of an Example // Values is string | number
type Values = ValueOf<{ a: string; b: number }>; |