TypeScript's largest utility library providing 200+ type utilities for advanced type manipulation.
—
Extensive object manipulation utilities providing property access, transformation operations, and deep path-based modifications. The second largest module with 55+ type utilities.
Access properties, check existence, and extract keys and values.
/**
* Access property at key K in object O
* @param O - Object type to access
* @param K - Key to access
* @returns Property type at key K
*/
type At<O extends Object, K extends keyof O> = O[K];
/**
* Check if object O has property K
* @param O - Object type to check
* @param K - Key to check for
* @returns 1 if property exists, 0 otherwise
*/
type Has<O extends Object, K extends Key> = K extends keyof O ? 1 : 0;
/**
* Extract all keys from object O
* @param O - Object type to extract keys from
* @returns Union of all keys
*/
type Keys<O extends Object> = keyof O;
/**
* Extract known keys (non-index signature) from object O
* @param O - Object type to extract known keys from
* @returns Union of known keys
*/
type KnownKeys<O extends Object> = keyof O;
/**
* Extract all values from object O
* @param O - Object type to extract values from
* @returns Union of all property values
*/
type Values<O extends Object> = O[keyof O];
/**
* Generate all possible paths to properties in object O
* @param O - Object type to generate paths for
* @returns Union of all property paths
*/
type Paths<O extends Object> = PathsImpl<O>;Usage Examples:
import { O } from "ts-toolbelt";
type User = {
name: string;
age: number;
address: { street: string; city: string };
};
type Name = O.At<User, "name">; // string
type HasEmail = O.Has<User, "email">; // 0
type HasName = O.Has<User, "name">; // 1
type UserKeys = O.Keys<User>; // "name" | "age" | "address"
type UserValues = O.Values<User>; // string | number | { street: string; city: string }
type UserPaths = O.Paths<User>; // "name" | "age" | "address" | "address.street" | "address.city"Additional key-based operations for filtering, selecting, and working with object keys.
/**
* Get the keys of O which fields match M
* @param O - Object to extract from
* @param M - Type to select fields
* @param match - Precision mode for matching
* @returns Union of keys whose values match M
*/
type SelectKeys<O extends Object, M extends any, match extends Match = 'default'> = SelectKeysImpl<O, M, match>;
/**
* Filter out the keys of O which fields match M
* @param O - Object to remove from
* @param M - Type to select fields
* @param match - Precision mode for matching
* @returns Union of keys whose values don't match M
*/
type FilterKeys<O extends Object, M extends any, match extends Match = 'default'> = FilterKeysImpl<O, M, match>;
/**
* Get the intersecting keys of O & O1
* @param O - Object to check similarities with
* @param O1 - Object to check similarities against
* @param match - Precision mode for matching
* @returns Union of common keys
*/
type IntersectKeys<O extends Object, O1 extends Object, match extends Match = 'default'> = IntersectKeysImpl<O, O1, match>;
/**
* Exclude the keys of O1 out of the keys of O
* @param O - Object to remove keys from
* @param O1 - Object whose keys to remove
* @param match - Precision mode for matching
* @returns Union of keys in O but not in O1
*/
type ExcludeKeys<O extends Object, O1 extends Object, match extends Match = 'default'> = ExcludeKeysImpl<O, O1, match>;Operations for working with nullable, non-nullable, and undefinable keys.
/**
* Get the keys of O that are non-nullable
* @param O - Object to extract from
* @returns Union of non-nullable keys
*/
type NonNullableKeys<O extends Object> = NonNullableKeysImpl<O>;
/**
* Get the keys of O that are nullable
* @param O - Object to extract from
* @returns Union of nullable keys
*/
type NullableKeys<O extends Object> = NullableKeysImpl<O>;
/**
* Get the keys of O that are undefinable
* @param O - Object to extract from
* @returns Union of undefinable keys
*/
type UndefinableKeys<O extends Object> = UndefinableKeysImpl<O>;Essential object transformation operations for creating new object types.
/**
* Pick specific properties from object O
* @param O - Object type to pick from
* @param K - Keys to pick
* @returns New object with only picked properties
*/
type Pick<O extends Object, K extends keyof O> = { [P in K]: O[P] } & {};
/**
* Omit specific properties from object O
* @param O - Object type to omit from
* @param K - Keys to omit
* @returns New object without omitted properties
*/
type Omit<O extends Object, K extends keyof O> = Pick<O, Exclude<keyof O, K>>;
/**
* Merge two objects with optional depth control
* @param O1 - First object to merge
* @param O2 - Second object to merge
* @param depth - Merge depth: 'flat' or 'deep'
* @returns Merged object type
*/
type Merge<O1 extends Object, O2 extends Object, depth extends 'flat' | 'deep' = 'flat'> =
depth extends 'flat' ? O1 & O2 : MergeDeep<O1, O2>;
/**
* Merge multiple objects into one
* @param Os - Array of object types to merge
* @returns Single merged object type
*/
type MergeAll<Os extends readonly Object[]> = MergeAllImpl<Os>;
/**
* Assign properties from source to target object
* @param O - Target object type
* @param O1 - Source object type
* @returns Object with assigned properties
*/
type Assign<O extends Object, O1 extends Object> = O & O1;Usage Examples:
import { O } from "ts-toolbelt";
type User = { name: string; age: number; email: string; active: boolean };
type BasicUser = O.Pick<User, "name" | "age">; // { name: string; age: number }
type PublicUser = O.Omit<User, "email">; // { name: string; age: number; active: boolean }
type Address = { street: string; city: string };
type UserWithAddress = O.Merge<User, Address>;
// { name: string; age: number; email: string; active: boolean; street: string; city: string }
// Deep merge example
type UserProfile = { user: { name: string } };
type UserDetails = { user: { age: number } };
type FullProfile = O.Merge<UserProfile, UserDetails, 'deep'>;
// { user: { name: string; age: number } }
type MultiMerge = O.MergeAll<[User, Address, { score: number }]>;
// { name: string; age: number; email: string; active: boolean; street: string; city: string; score: number }Advanced object operations including exclusion, intersection, and validation.
/**
* Exclude the fields of O1 out of O
* @param O - Object to remove from
* @param O1 - Object whose fields to remove
* @param match - Precision mode for matching
* @returns Object with O1 fields removed
*/
type Exclude<O extends Object, O1 extends Object, match extends Match = 'default'> = Pick<O, ExcludeKeys<O, O1, match>>;
/**
* Get the intersecting fields of O & O1
* @param O - Object to check similarities with
* @param O1 - Object to check similarities against
* @param match - Precision mode for matching
* @returns Object with only common fields
*/
type Intersect<O extends Object, O1 extends Object, match extends Match = 'default'> = Pick<O, IntersectKeys<O, O1, match>>;
/**
* Check whether O has fields that match M
* @param O - Object to be inspected
* @param M - Type to check field type
* @param match - Precision mode for matching
* @returns 1 if match found, 0 otherwise
*/
type Includes<O extends Object, M extends any, match extends Match = 'default'> = [SelectKeys<O, M, match>] extends [never] ? 0 : 1;
/**
* Swap the keys and values of an object
* @param O - Object to invert
* @returns Object with keys and values swapped
*/
type Invert<O extends Record<keyof O, Key>> = InvertImpl<O>;
/**
* Make the fields of O union the ones of O1
* @param O - Object to union from
* @param O1 - Object to union with
* @param K - Keys to choose fields
* @returns Object with unionized field types
*/
type Unionize<O extends Object, O1 extends Object, K extends Key = Key> = {
[P in keyof O]: P extends K ? O[P] | At<O1, P> : O[P];
} & {};Operations for applying constraints and requirements to object types.
/**
* Make that at least one of the keys K are required in O at a time
* @param O - Object to make required
* @param K - Keys to choose fields
* @returns Object union with at least one required key
*/
type AtLeast<O extends object, K extends Key = Keys<O>> = O extends unknown ? _AtLeast<O, K> : never;
/**
* Split O into a union where none of the K keys are present together
* @param O - Object to split
* @param K - Keys to split with
* @param strict - Force excess property checks
* @returns Object union with mutually exclusive keys
*/
type Either<O extends object, K extends Key, strict extends Boolean = 1> = O extends unknown ? _Either<O, K, strict> : never;Operations for transforming objects into other types.
/**
* Transform an object into a list
* @param O - Object to transform
* @returns List representation of object
*/
type ListOf<O extends Object> = ListOfImpl<O>;
/**
* Transform an object into a union of its values
* @param O - Object to transform
* @returns Union of all property values
*/
type UnionOf<O extends Object> = UnionOfImpl<O>;
/**
* Merge a list of objects into O
* @param O - Object to start with
* @param Os - List of objects to merge
* @param depth - Merge depth ('flat' or 'deep')
* @param ignore - Types not to merge
* @param fill - Types to be replaced
* @returns Merged object
*/
type MergeAll<O extends Object, Os extends List<Object>, depth extends Depth = 'flat', ignore extends Object = BuiltIn, fill extends any = undefined> = MergeAllImpl<O, Os, depth, ignore, fill>;
/**
* Patch a list of objects into O
* @param O - Object to start with
* @param Os - List of objects to patch
* @param depth - Patch depth ('flat' or 'deep')
* @param ignore - Types not to merge
* @param fill - Types to be replaced
* @returns Patched object
*/
type PatchAll<O extends Object, Os extends List<Object>, depth extends Depth = 'flat', ignore extends Object = BuiltIn, fill extends any = never> = PatchAllImpl<O, Os, depth, ignore, fill>;Core utility types for object operations.
/**
* An Object type
* @returns Record with any keys and values
*/
type Object = Record<Key, any>;
/**
* Create an object filled with A for the fields K
* @param K - Keys to choose fields
* @param A - Type to fill fields with
* @param modx - Modifiers for readonly/optional
* @returns Object record type
*/
type Record<K extends Key, A extends any = unknown, modx extends Modx = ['!', 'W']> = {
'!': {
'R': { readonly [P in K]: A };
'W': { [P in K]: A };
};
'?': {
'R': { readonly [P in K]?: A };
'W': { [P in K]?: A };
};
}[modx[0]][modx[1]];Modify property characteristics like optionality, readonly status, and nullability.
/**
* Make all properties optional
* @param O - Object type to make partial
* @returns Object with all optional properties
*/
type Partial<O extends Object> = { [K in keyof O]?: O[K] };
/**
* Make all properties required
* @param O - Object type to make required
* @returns Object with all required properties
*/
type Required<O extends Object> = { [K in keyof O]-?: O[K] };
/**
* Make all properties readonly
* @param O - Object type to make readonly
* @returns Object with all readonly properties
*/
type Readonly<O extends Object> = { readonly [K in keyof O]: O[K] };
/**
* Make all properties writable (remove readonly)
* @param O - Object type to make writable
* @returns Object with all writable properties
*/
type Writable<O extends Object> = { -readonly [K in keyof O]: O[K] };
/**
* Make all properties nullable
* @param O - Object type to make nullable
* @returns Object with all nullable properties
*/
type Nullable<O extends Object> = { [K in keyof O]: O[K] | null };
/**
* Remove null and undefined from all properties
* @param O - Object type to make non-nullable
* @returns Object with non-nullable properties
*/
type NonNullable<O extends Object> = { [K in keyof O]: NonNullable<O[K]> };
/**
* Make specific properties compulsory (required)
* @param O - Object type to modify
* @param K - Keys to make compulsory
* @returns Object with specified properties made required
*/
type Compulsory<O extends Object, K extends keyof O> = O & Required<Pick<O, K>>;
/**
* Make specific properties optional
* @param O - Object type to modify
* @param K - Keys to make optional
* @returns Object with specified properties made optional
*/
type Optional<O extends Object, K extends keyof O> = Omit<O, K> & Partial<Pick<O, K>>;Usage Examples:
import { O } from "ts-toolbelt";
type User = {
readonly name: string;
age: number;
email?: string;
active: boolean | null;
};
type PartialUser = O.Partial<User>;
// { readonly name?: string; age?: number; email?: string; active?: boolean | null }
type RequiredUser = O.Required<User>;
// { readonly name: string; age: number; email: string; active: boolean | null }
type ReadonlyUser = O.Readonly<User>;
// { readonly name: string; readonly age: number; readonly email?: string; readonly active: boolean | null }
type WritableUser = O.Writable<User>;
// { name: string; age: number; email?: string; active: boolean | null }
type NullableUser = O.Nullable<User>;
// { readonly name: string | null; age: number | null; email?: string | null; active: boolean | null }
type NonNullUser = O.NonNullable<User>;
// { readonly name: string; age: number; email?: string; active: boolean }
type CompulsoryEmail = O.Compulsory<User, "email">;
// { readonly name: string; age: number; email: string; active: boolean | null }
type OptionalAge = O.Optional<User, "age">;
// { readonly name: string; age?: number; email?: string; active: boolean | null }Advanced property manipulation including filtering, updating, and selective operations.
/**
* Filter object properties based on condition
* @param O - Object type to filter
* @param M - Condition to filter by
* @returns Object with filtered properties
*/
type Filter<O extends Object, M> = FilterImpl<O, M>;
/**
* Update specific properties with new values
* @param O - Object type to update
* @param Path - Path to property to update
* @param A - New value type
* @returns Object with updated property
*/
type Update<O extends Object, Path extends string, A> = UpdateImpl<O, Path, A>;
/**
* Modify properties using transformation function
* @param O - Object type to modify
* @param M - Modification mapping
* @returns Object with modified properties
*/
type Modify<O extends Object, M> = ModifyImpl<O, M>;
/**
* Replace properties with new types
* @param O - Object type to modify
* @param M - Replacement mapping
* @returns Object with replaced properties
*/
type Replace<O extends Object, M extends Object> = Omit<O, keyof M> & M;
/**
* Patch object with new properties (shallow merge)
* @param O - Object type to patch
* @param O1 - Properties to patch with
* @returns Patched object
*/
type Patch<O extends Object, O1 extends Object> = O & O1;
/**
* Overwrite properties from source object
* @param O - Target object type
* @param O1 - Source object type
* @param K - Keys to overwrite
* @returns Object with overwritten properties
*/
type Overwrite<O extends Object, O1 extends Object, K extends keyof O & keyof O1 = keyof O & keyof O1> =
Omit<O, K> & Pick<O1, K>;Usage Examples:
import { O } from "ts-toolbelt";
type User = { name: string; age: number; email: string; active: boolean };
// Filter only string properties
type StringProps = O.Filter<User, string>; // { name: string; email: string }
// Update nested property
type UserProfile = { user: User; settings: { theme: string } };
type UpdatedProfile = O.Update<UserProfile, "settings.theme", "dark">;
// { user: User; settings: { theme: "dark" } }
// Replace properties
type UserUpdates = { age: string; score: number };
type UpdatedUser = O.Replace<User, UserUpdates>;
// { name: string; age: string; email: string; active: boolean; score: number }
// Patch with new properties
type UserExtensions = { lastLogin: Date; preferences: string[] };
type ExtendedUser = O.Patch<User, UserExtensions>;
// { name: string; age: number; email: string; active: boolean; lastLogin: Date; preferences: string[] }
// Overwrite specific properties
type NewUserData = { age: string; active: string };
type OverwrittenUser = O.Overwrite<User, NewUserData>;
// { name: string; age: string; email: string; active: string }Deep object manipulation using path notation for nested property access.
/**
* Path-based property access using dot notation
* @param O - Object type to access
* @param Path - Dot-separated path to property
* @returns Property type at path
*/
type AtPath<O extends Object, Path extends string> = AtPathImpl<O, Path>;
/**
* Check if path exists in object
* @param O - Object type to check
* @param Path - Path to check for
* @returns 1 if path exists, 0 otherwise
*/
type HasPath<O extends Object, Path extends string> = HasPathImpl<O, Path>;
/**
* Namespace for path-based operations
*/
namespace P {
type Pick<O extends Object, Path extends string> = PickPathImpl<O, Path>;
type Omit<O extends Object, Path extends string> = OmitPathImpl<O, Path>;
type Update<O extends Object, Path extends string, A> = UpdatePathImpl<O, Path, A>;
type Merge<O1 extends Object, O2 extends Object> = MergePathImpl<O1, O2>;
type Readonly<O extends Object, Path extends string> = ReadonlyPathImpl<O, Path>;
type Record<Path extends string, A> = RecordPathImpl<Path, A>;
}Usage Examples:
import { O } from "ts-toolbelt";
type UserProfile = {
user: {
name: string;
details: {
age: number;
address: {
street: string;
city: string;
};
};
};
settings: {
theme: string;
notifications: boolean;
};
};
type UserName = O.AtPath<UserProfile, "user.name">; // string
type UserAge = O.AtPath<UserProfile, "user.details.age">; // number
type City = O.AtPath<UserProfile, "user.details.address.city">; // string
type HasTheme = O.HasPath<UserProfile, "settings.theme">; // 1
type HasInvalidPath = O.HasPath<UserProfile, "user.invalid">; // 0
// Path-based operations using P namespace
type PickUserName = O.P.Pick<UserProfile, "user.name">;
// { user: { name: string } }
type UpdateAge = O.P.Update<UserProfile, "user.details.age", string>;
// UserProfile with age changed to string
type MergeSettings = O.P.Merge<UserProfile, { settings: { language: string } }>;
// UserProfile with settings.language addedExtract different types of keys based on property characteristics.
/**
* Extract keys of properties that are optional
* @param O - Object type to extract from
* @returns Union of optional property keys
*/
type OptionalKeys<O extends Object> = OptionalKeysImpl<O>;
/**
* Extract keys of properties that are required
* @param O - Object type to extract from
* @returns Union of required property keys
*/
type RequiredKeys<O extends Object> = RequiredKeysImpl<O>;
/**
* Extract keys of properties that are readonly
* @param O - Object type to extract from
* @returns Union of readonly property keys
*/
type ReadonlyKeys<O extends Object> = ReadonlyKeysImpl<O>;
/**
* Extract keys of properties that are writable
* @param O - Object type to extract from
* @returns Union of writable property keys
*/
type WritableKeys<O extends Object> = WritableKeysImpl<O>;
/**
* Extract keys of properties that can be undefined
* @param O - Object type to extract from
* @returns Union of undefinable property keys
*/
type UndefinableKeys<O extends Object> = UndefinableKeysImpl<O>;
/**
* Extract keys of properties that are compulsory (required and not undefined)
* @param O - Object type to extract from
* @returns Union of compulsory property keys
*/
type CompulsoryKeys<O extends Object> = CompulsoryKeysImpl<O>;Usage Examples:
import { O } from "ts-toolbelt";
type User = {
readonly id: string;
name: string;
age?: number;
email?: string;
active: boolean | undefined;
};
type OptionalKeys = O.OptionalKeys<User>; // "age" | "email"
type RequiredKeys = O.RequiredKeys<User>; // "id" | "name" | "active"
type ReadonlyKeys = O.ReadonlyKeys<User>; // "id"
type WritableKeys = O.WritableKeys<User>; // "name" | "age" | "email" | "active"
type UndefinableKeys = O.UndefinableKeys<User>; // "age" | "email" | "active"
type CompulsoryKeys = O.CompulsoryKeys<User>; // "id" | "name"// Core types used by Object module
type Object = Record<string | number | symbol, any>;
type Key = string | number | symbol;Install with Tessl CLI
npx tessl i tessl/npm-ts-toolbelt