TypeScript's largest utility library providing 200+ type utilities for advanced type manipulation.
—
Comprehensive array and tuple manipulation utilities - the largest module with 73+ operations for transforming, accessing, and modifying list types.
Essential operations for adding, removing, and rearranging list elements.
/**
* Add element to the end of list
* @param L - List to append to
* @param A - Element to append
* @returns New list with element appended
*/
type Append<L extends List, A> = [...L, A];
/**
* Add element to the beginning of list
* @param L - List to prepend to
* @param A - Element to prepend
* @returns New list with element prepended
*/
type Prepend<L extends List, A> = [A, ...L];
/**
* Concatenate two lists
* @param L1 - First list
* @param L2 - Second list
* @returns Combined list
*/
type Concat<L1 extends List, L2 extends List> = [...L1, ...L2];
/**
* Reverse the order of elements in list
* @param L - List to reverse
* @returns List with elements in reverse order
*/
type Reverse<L extends List> = ReverseImpl<L>;
/**
* Remove last element from list
* @param L - List to pop from
* @returns List without last element
*/
type Pop<L extends List> = L extends readonly [...infer Rest, any] ? Rest : [];
/**
* Remove first N elements from list
* @param L - List to drop from
* @param N - Number of elements to drop
* @returns List without first N elements
*/
type Drop<L extends List, N extends number> = DropImpl<L, N>;
/**
* Take first N elements from list
* @param L - List to take from
* @param N - Number of elements to take
* @returns List with only first N elements
*/
type Take<L extends List, N extends number> = TakeImpl<L, N>;Usage Examples:
import { L } from "ts-toolbelt";
type Numbers = [1, 2, 3];
type Letters = ["a", "b"];
type WithFour = L.Append<Numbers, 4>; // [1, 2, 3, 4]
type WithZero = L.Prepend<Numbers, 0>; // [0, 1, 2, 3]
type Combined = L.Concat<Numbers, Letters>; // [1, 2, 3, "a", "b"]
type Reversed = L.Reverse<Numbers>; // [3, 2, 1]
type Popped = L.Pop<Numbers>; // [1, 2]
type DropTwo = L.Drop<[1, 2, 3, 4, 5], 2>; // [3, 4, 5]
type TakeTwo = L.Take<[1, 2, 3, 4, 5], 2>; // [1, 2]Get specific elements and information from lists.
/**
* Get element at specific index
* @param L - List to access
* @param K - Index to access
* @returns Element at index K
*/
type At<L extends List, K extends number> = L[K];
/**
* Get first element of list
* @param L - List to get head from
* @returns First element or never if empty
*/
type Head<L extends List> = L extends readonly [infer H, ...any[]] ? H : never;
/**
* Get all elements except first
* @param L - List to get tail from
* @returns List without first element
*/
type Tail<L extends List> = L extends readonly [any, ...infer T] ? T : [];
/**
* Get last element of list
* @param L - List to get last from
* @returns Last element or never if empty
*/
type Last<L extends List> = L extends readonly [...any[], infer L] ? L : never;
/**
* Get length of list
* @param L - List to measure
* @returns Length as number literal
*/
type Length<L extends List> = L['length'];
/**
* Extract valid keys (indices) from list
* @param L - List to extract keys from
* @returns Union of valid indices
*/
type Keys<L extends List> = Exclude<keyof L, keyof []>;
/**
* Extract known keys (non-index signature) from list
* @param L - List to extract known keys from
* @returns Union of known indices
*/
type KnownKeys<L extends List> = KnownKeysImpl<L>;Usage Examples:
import { L } from "ts-toolbelt";
type Items = ["apple", "banana", "cherry"];
type Second = L.At<Items, 1>; // "banana"
type First = L.Head<Items>; // "apple"
type Rest = L.Tail<Items>; // ["banana", "cherry"]
type Last = L.Last<Items>; // "cherry"
type Count = L.Length<Items>; // 3
type Indices = L.Keys<Items>; // 0 | 1 | 2
type KnownIndices = L.KnownKeys<Items>; // 0 | 1 | 2
// With mixed tuple
type Mixed = [string, number, ...boolean[]];
type MixedKeys = L.Keys<Mixed>; // number (includes index signature)
type MixedKnown = L.KnownKeys<Mixed>; // 0 | 1Check membership, inclusion, and constraints on lists.
/**
* Check if list contains specific element
* @param L - List to check
* @param A - Element to look for
* @returns 1 if element is found, 0 otherwise
*/
type Has<L extends List, A> = A extends L[number] ? 1 : 0;
/**
* Check if list includes element (alias for Has)
* @param L - List to check
* @param A - Element to look for
* @returns 1 if element is included, 0 otherwise
*/
type Includes<L extends List, A> = Has<L, A>;
/**
* Ensure list has at least N elements
* @param L - List to check
* @param N - Minimum number
* @returns List type with at least N elements constraint
*/
type AtLeast<L extends List, N extends number> = AtLeastImpl<L, N>;Usage Examples:
import { L } from "ts-toolbelt";
type Fruits = ["apple", "banana", "cherry"];
type HasApple = L.Has<Fruits, "apple">; // 1
type HasOrange = L.Has<Fruits, "orange">; // 0
type IncludesBanana = L.Includes<Fruits, "banana">; // 1
// AtLeast constraint
type AtLeastTwo = L.AtLeast<[string, number], 2>; // [string, number]
type AtLeastFive = L.AtLeast<[string], 5>; // Constraint ensures minimum 5 elementsTransform lists using mapping, filtering, and grouping operations.
/**
* Filter list elements based on condition
* @param L - List to filter
* @param M - Condition to filter by
* @returns List with elements matching condition
*/
type Filter<L extends List, M> = FilterImpl<L, M>;
/**
* Group list elements by criteria
* @param L - List to group
* @param K - Grouping criteria
* @returns Grouped structure
*/
type Group<L extends List, K> = GroupImpl<L, K>;
/**
* Flatten nested lists
* @param L - List to flatten
* @param depth - Flatten depth
* @returns Flattened list
*/
type Flatten<L extends List, depth extends number = 1> = FlattenImpl<L, depth>;
/**
* Zip two lists together
* @param L1 - First list
* @param L2 - Second list
* @returns List of paired elements
*/
type Zip<L1 extends List, L2 extends List> = ZipImpl<L1, L2>;
/**
* Create object from list of keys and list of values
* @param K - List of keys
* @param V - List of values
* @returns Object with zipped key-value pairs
*/
type ZipObj<K extends readonly (string | number | symbol)[], V extends List> = ZipObjImpl<K, V>;
/**
* Convert list to object with indices as keys
* @param L - List to convert
* @returns Object representation of list
*/
type ObjectOf<L extends List> = { [K in keyof L]: L[K] };
/**
* Convert object to list of values
* @param O - Object to convert
* @returns List of object values
*/
type ListOf<O extends Record<number, any>> = ListOfImpl<O>;Usage Examples:
import { L } from "ts-toolbelt";
type Numbers = [1, 2, 3, 4, 5];
type Mixed = [string, number, boolean];
// Filter even numbers (conceptual - actual implementation varies)
type EvenNumbers = L.Filter<Numbers, 2 | 4>; // [2, 4]
// Zip lists
type List1 = ["a", "b", "c"];
type List2 = [1, 2, 3];
type Zipped = L.Zip<List1, List2>; // [["a", 1], ["b", 2], ["c", 3]]
// Zip to object
type Keys = ["name", "age", "active"];
type Values = [string, number, boolean];
type UserSchema = L.ZipObj<Keys, Values>; // { name: string; age: number; active: boolean }
// List to object conversion
type ListAsObj = L.ObjectOf<["a", "b", "c"]>; // { 0: "a"; 1: "b"; 2: "c" }
// Object to list conversion
type ObjAsList = L.ListOf<{ 0: "a"; 1: "b"; 2: "c" }>; // ["a", "b", "c"]
// Flatten nested arrays
type Nested = [[1, 2], [3, [4, 5]]];
type FlatOnce = L.Flatten<Nested>; // [1, 2, 3, [4, 5]]
type FlatDeep = L.Flatten<Nested, 2>; // [1, 2, 3, 4, 5]Operations treating lists as sets for intersection, difference, and exclusion.
/**
* Set difference - elements in L1 but not in L2
* @param L1 - First list
* @param L2 - Second list
* @returns Elements unique to first list
*/
type Diff<L1 extends List, L2 extends List> = DiffImpl<L1, L2>;
/**
* Set intersection - elements common to both lists
* @param L1 - First list
* @param L2 - Second list
* @returns Common elements
*/
type Intersect<L1 extends List, L2 extends List> = IntersectImpl<L1, L2>;
/**
* Exclude specific elements from list
* @param L - List to exclude from
* @param A - Elements to exclude
* @returns List without excluded elements
*/
type Exclude<L extends List, A> = ExcludeImpl<L, A>;
/**
* Extract specific elements from list
* @param L - List to extract from
* @param A - Elements to extract
* @returns List with only extracted elements
*/
type Extract<L extends List, A> = ExtractImpl<L, A>;
/**
* Remove duplicate elements from list
* @param L - List to deduplicate
* @returns List with unique elements only
*/
type Unique<L extends List> = UniqueImpl<L>;Usage Examples:
import { L } from "ts-toolbelt";
type List1 = [1, 2, 3, 4];
type List2 = [3, 4, 5, 6];
type Difference = L.Diff<List1, List2>; // [1, 2]
type Common = L.Intersect<List1, List2>; // [3, 4]
type WithoutNumbers = L.Exclude<[1, "a", 2, "b"], number>; // ["a", "b"]
type OnlyNumbers = L.Extract<[1, "a", 2, "b"], number>; // [1, 2]
type WithDuplicates = [1, 2, 2, 3, 3, 3];
type UniqueOnly = L.Unique<WithDuplicates>; // [1, 2, 3]Operations for working with list keys, indices, and key-based filtering.
/**
* Get the keys of L which entries match M
* @param L - List to extract from
* @param M - Type to select entries
* @param match - Precision mode for matching
* @returns Union of keys whose values match M
*/
type SelectKeys<L extends List, M extends any, match extends Match = 'default'> = SelectKeysImpl<L, M, match>;
/**
* Filter out the keys of L which entries match M
* @param L - List to remove from
* @param M - Type to select entries
* @param match - Precision mode for matching
* @returns Union of keys whose values don't match M
*/
type FilterKeys<L extends List, M extends any, match extends Match = 'default'> = FilterKeysImpl<L, M, match>;
/**
* Get the intersecting keys of L & L1
* @param L - List to check similarities with
* @param L1 - List to check similarities against
* @param match - Precision mode for matching
* @returns Union of common keys
*/
type IntersectKeys<L extends List, L1 extends List, match extends Match = 'default'> = IntersectKeysImpl<L, L1, match>;
/**
* Create a set of keys from range
* @param From - Starting index
* @param To - Ending index
* @returns Union of keys in range
*/
type KeySet<From extends number, To extends number> = KeySetImpl<From, To>;
/**
* Get the last index of L
* @param L - List to get last index from
* @returns Last valid index number
*/
type LastKey<L extends List> = Length<Tail<L>>;Operations for categorizing keys by their type characteristics.
/**
* Get the keys of L that are optional
* @param L - List to extract from
* @returns Union of optional keys
*/
type OptionalKeys<L extends List> = OptionalKeysImpl<L>;
/**
* Get the keys of L that are required
* @param L - List to extract from
* @returns Union of required keys
*/
type RequiredKeys<L extends List> = RequiredKeysImpl<L>;
/**
* Get the keys of L that are readonly
* @param L - List to extract from
* @returns Union of readonly keys
*/
type ReadonlyKeys<L extends List> = ReadonlyKeysImpl<L>;
/**
* Get the keys of L that are writable
* @param L - List to extract from
* @returns Union of writable keys
*/
type WritableKeys<L extends List> = WritableKeysImpl<L>;
/**
* Get the keys of L that are nullable
* @param L - List to extract from
* @returns Union of nullable keys
*/
type NullableKeys<L extends List> = NullableKeysImpl<L>;
/**
* Get the keys of L that are non-nullable
* @param L - List to extract from
* @returns Union of non-nullable keys
*/
type NonNullableKeys<L extends List> = NonNullableKeysImpl<L>;
/**
* Get the keys of L that are undefinable
* @param L - List to extract from
* @returns Union of undefinable keys
*/
type UndefinableKeys<L extends List> = UndefinableKeysImpl<L>;Operations for navigating and accessing nested properties in lists.
/**
* Get the type at nested path in L
* @param L - List to be inspected
* @param Path - Path to be followed
* @returns Type at the specified path
*/
type Path<L extends List, Path extends List<Key>> = PathImpl<L, Path>;
/**
* Get all possible paths of L
* @param L - List to be inspected
* @returns Union of all possible paths
*/
type Paths<L extends List> = PathsImpl<L>;
/**
* Check whether L has nested entries that match M
* @param L - List to be inspected
* @param Path - Path to be followed
* @param M - Type to check entry type
* @param match - Precision mode for matching
* @returns 1 if path exists and matches, 0 otherwise
*/
type HasPath<L extends List, Path extends List<Key>, M extends any = any, match extends Match = 'default'> = HasPathImpl<L, Path, M, match>;Operations for extracting and removing ranges of elements.
/**
* Pick a range of entries from L
* @param L - List to pick from
* @param From - Starting index
* @param To - Ending index
* @returns List containing elements in range
*/
type Extract<L extends List, From extends number, To extends number> = Pick<L, KeySet<From, To>>;
/**
* Remove a range of entries from L
* @param L - List to remove from
* @param From - Starting index
* @param To - Ending index
* @returns List without elements in range
*/
type Remove<L extends List, From extends number, To extends number> = Omit<L, KeySet<From, To>>;Advanced operations for modifying, patching, and updating list elements.
/**
* Assign a list of Lists into L with Merge
* @param L - List to assign to
* @param Ls - Lists to assign
* @param depth - Merge depth ('flat' or 'deep')
* @param ignore - Types not to merge
* @param fill - Types to be replaced
* @returns Modified list
*/
type Assign<L extends List, Ls extends List<List>, depth extends Depth = 'flat', ignore extends object = BuiltIn, fill extends any = never> = Cast<OAssign<L, Ls, depth, ignore, fill>, List>;
/**
* Update the entries of L with the ones of L1
* @param L - List to update
* @param L1 - List to update with
* @returns Updated list
*/
type Overwrite<L extends List, L1 extends object> = OverwriteImpl<L, L1>;
/**
* Modify L with LMod using placeholder substitution
* @param L - List to copy from
* @param LMod - Modification template
* @returns Modified list
*/
type Modify<L extends List, LMod extends List> = ModifyImpl<L, LMod>;
/**
* Complete the fields of L with the ones of L1
* @param L - List to complete
* @param L1 - List to copy from
* @param depth - Patch depth ('flat' or 'deep')
* @param ignore - Types not to merge
* @param fill - Types to be replaced
* @returns Patched list
*/
type Patch<L extends List, L1 extends List, depth extends Depth = 'flat', ignore extends object = BuiltIn, fill extends any = never> = PatchImpl<L, L1, depth, ignore, fill>;
/**
* Patch a list of Lists into L
* @param L - List to start with
* @param Ls - Lists to patch
* @param depth - Patch depth ('flat' or 'deep')
* @param ignore - Types not to merge
* @param fill - Types to be replaced
* @returns Patched list
*/
type PatchAll<L extends List, Ls extends List<List>, depth extends Depth = 'flat', ignore extends object = BuiltIn, fill extends any = never> = PatchAllImpl<L, Ls, depth, ignore, fill>;Utility operations for list generation, comparison, and transformation.
/**
* Fill a List with N repetitions of A
* @param A - Element to fill with
* @param N - Number of repetitions
* @param L - Initial list (empty by default)
* @returns List filled with repeated elements
*/
type Repeat<A extends any, N extends number, L extends List = []> = RepeatImpl<A, N, L>;
/**
* Transform a List into a Union
* @param L - List to transform
* @returns Union of all list elements
*/
type UnionOf<L extends List> = L[number];
/**
* Remove a dimension from nested L
* @param L - List to un-nest
* @param strict - Whether to preserve tuples
* @returns Flattened list
*/
type UnNest<L extends List, strict extends Boolean = 1> = UnNestImpl<L, strict>;
/**
* Get the longest List of L & L1
* @param L - First list to compare
* @param L1 - Second list to compare
* @returns Longer of the two lists
*/
type Longest<L extends List, L1 extends List> = LongestImpl<L, L1>;
/**
* Get the shortest List of L & L1
* @param L - First list to compare
* @param L1 - Second list to compare
* @returns Shorter of the two lists
*/
type Shortest<L extends List, L1 extends List> = ShortestImpl<L, L1>;
/**
* Split L into a Union where none of the K keys are present together
* @param L - List to split
* @param K - Keys to split with
* @param strict - Force excess property checks
* @returns List union with mutually exclusive keys
*/
type Either<L extends List, K extends Key, strict extends Boolean = 1> = OEither<ObjectOf<L>, `${K & number}` | K, strict> extends infer OE ? OE extends unknown ? _ListOf<OE & {}> : never : never;Modify characteristics of list elements like optionality, nullability, and readonly status.
/**
* Make all list elements optional
* @param L - List to make partial
* @returns List with optional elements
*/
type Partial<L extends List> = { [K in keyof L]?: L[K] };
/**
* Make all list elements required
* @param L - List to make required
* @returns List with required elements
*/
type Required<L extends List> = { [K in keyof L]-?: L[K] };
/**
* Make all list elements readonly
* @param L - List to make readonly
* @returns Readonly list
*/
type Readonly<L extends List> = { readonly [K in keyof L]: L[K] };
/**
* Make all list elements writable
* @param L - List to make writable
* @returns Writable list
*/
type Writable<L extends List> = { -readonly [K in keyof L]: L[K] };
/**
* Make all list elements nullable
* @param L - List to make nullable
* @returns List with nullable elements
*/
type Nullable<L extends List> = { [K in keyof L]: L[K] | null };
/**
* Remove null and undefined from all list elements
* @param L - List to make non-nullable
* @returns List with non-nullable elements
*/
type NonNullable<L extends List> = { [K in keyof L]: NonNullable<L[K]> };
/**
* Make all list elements undefinable
* @param L - List to make undefinable
* @returns List with undefinable elements
*/
type Undefinable<L extends List> = { [K in keyof L]: L[K] | undefined };Usage Examples:
import { L } from "ts-toolbelt";
type StrictList = readonly [string, number, boolean];
type OptionalList = L.Partial<StrictList>; // [string?, number?, boolean?]
type RequiredList = L.Required<OptionalList>; // [string, number, boolean]
type ReadonlyList = L.Readonly<[string, number]>; // readonly [string, number]
type WritableList = L.Writable<ReadonlyList>; // [string, number]
type NullableList = L.Nullable<[string, number]>; // [string | null, number | null]
type NonNullList = L.NonNullable<[string | null, number | undefined]>; // [string, number]
type UndefinableList = L.Undefinable<[string, number]>; // [string | undefined, number | undefined]Complex operations for merging, updating, and transforming lists.
/**
* Merge two lists element-wise
* @param L1 - First list
* @param L2 - Second list
* @returns Merged list
*/
type Merge<L1 extends List, L2 extends List> = MergeImpl<L1, L2>;
/**
* Merge multiple lists
* @param Ls - Array of lists to merge
* @returns Single merged list
*/
type MergeAll<Ls extends readonly List[]> = MergeAllImpl<Ls>;
/**
* Update element at specific index
* @param L - List to update
* @param K - Index to update
* @param A - New value
* @returns List with updated element
*/
type Update<L extends List, K extends number, A> = UpdateImpl<L, K, A>;
/**
* Remove elements at specific indices
* @param L - List to remove from
* @param K - Indices to remove
* @returns List without removed elements
*/
type Remove<L extends List, K extends number> = RemoveImpl<L, K>;
/**
* Replace all occurrences of element
* @param L - List to replace in
* @param From - Element to replace
* @param To - Replacement element
* @returns List with replacements
*/
type Replace<L extends List, From, To> = ReplaceImpl<L, From, To>;
/**
* Select elements based on condition
* @param L - List to select from
* @param C - Selection condition
* @returns Selected elements
*/
type Select<L extends List, C> = SelectImpl<L, C>;
/**
* Convert list to union type
* @param L - List to unionize
* @returns Union of all list elements
*/
type Unionize<L extends List> = L[number];Usage Examples:
import { L } from "ts-toolbelt";
type List1 = [1, 2, 3];
type List2 = ["a", "b", "c"];
type Merged = L.Merge<List1, List2>; // [1 | "a", 2 | "b", 3 | "c"]
type MergedMultiple = L.MergeAll<[List1, List2, [true, false, true]]>;
// [1 | "a" | true, 2 | "b" | false, 3 | "c" | true]
type Updated = L.Update<[1, 2, 3], 1, "two">; // [1, "two", 3]
type Removed = L.Remove<[1, 2, 3, 4], 1>; // [1, 3, 4]
type Replaced = L.Replace<[1, 2, 1, 3], 1, "one">; // ["one", 2, "one", 3]
type AsUnion = L.Unionize<["a", "b", "c"]>; // "a" | "b" | "c"// Core types used by List module
type List<A = any> = readonly A[];Install with Tessl CLI
npx tessl i tessl/npm-ts-toolbelt