ts-essentials and ts-toolbelt are both powerful libraries designed to extend TypeScript's built-in type system with advanced utility types. ts-essentials focuses on providing a curated set of high-value, commonly needed types like DeepPartial, ValueOf, and MarkRequired that solve frequent pain points in enterprise application development. It prioritizes stability, readability, and ease of adoption. ts-toolbelt, by contrast, offers an exhaustive collection of over 300 utility types, covering complex scenarios involving lists, numbers, strings, and deep object manipulation. It acts as a comprehensive toolkit for developers who need to perform intricate type-level programming or build highly generic libraries where standard TypeScript utilities fall short.
When TypeScript's built-in utility types like Partial, Pick, or Record aren't enough, developers often reach for community libraries. ts-essentials and ts-toolbelt are the two leading options, but they serve very different needs. One is a focused toolkit for daily engineering tasks, while the other is an exhaustive encyclopedia of type manipulation. Let's break down how they differ in practice.
ts-essentials follows a "less is more" approach.
// ts-essentials: Common, high-value types
import { DeepPartial, ValueOf } from 'ts-essentials';
// DeepPartial makes every nested property optional
type Config = DeepPartial<{ db: { host: string; port: number } }>;
// Result: { db?: { host?: string; port?: number } }
// ValueOf extracts the union of all values from an object
type Roles = ValueOf<{ admin: 'admin'; user: 'user' }>;
// Result: 'admin' | 'user'
ts-toolbelt aims to be the "standard library" for type-level programming.
// ts-toolbelt: Advanced, niche capabilities
import { List, Number } from 'ts-toolbelt';
// Sort a tuple of numbers at the type level
type Sorted = List.Sort<[3, 1, 2]>;
// Result: [1, 2, 3]
// Perform math operations on types
type Sum = Number.Add<5, 10>;
// Result: 15
Both libraries excel at transforming object types, but they offer different levels of control.
ts-essentials provides straightforward wrappers for deep modifications.
DeepPartial, DeepRequired, and MarkOptional are easy to read and use.// ts-essentials: Simple deep modification
import { MarkRequired } from 'ts-essentials';
type User = { id?: string; name: string; email?: string };
// Make 'id' and 'email' required, leave 'name' as is
type CompleteUser = MarkRequired<User, 'id' | 'email'>;
// Result: { id: string; name: string; email: string }
ts-toolbelt offers granular control over every aspect of an object.
// ts-toolbelt: Granular object construction
import { Object } from 'ts-toolbelt';
type User = { id: string; name: string; role: string };
// Merge two types with specific overwrite rules
type AdminUser = Object.Merge<User, { role: 'admin' }>;
// Result: { id: string; name: string; role: 'admin' }
// Pick keys matching a specific pattern
type StringFields = Object.Pick<User, string>; // Hypothetical pattern match
This is where the two libraries diverge significantly.
ts-essentials does not focus on primitive manipulation.
// ts-essentials: No native support for type-level math
// You would need to implement custom logic or use another library
// There is no built-in Add<1, 2> or Length<string>
ts-toolbelt shines in this area with dedicated modules for primitives.
Number, String, List, and Boolean operations.// ts-toolbelt: Type-level string and list operations
import { String, List } from 'ts-toolbelt';
// Check if a string type ends with a specific suffix
type IsTsFile = String.EndsWith<'index.ts', '.ts'>;
// Result: true (as a type-level boolean)
// Get the length of a tuple
type Len = List.Length<[1, 2, 3]>;
// Result: 3
ts-essentials is beginner-friendly and stable.
// ts-essentials: Intuitive naming
import { Exact } from 'ts-essentials';
// Ensures a type matches exactly, no extra keys
function process<T>(arg: Exact<T, typeof arg>) { /*...*/ }
ts-toolbelt requires a deeper understanding of type-level programming.
// ts-toolbelt: Complex abstractions
import { Any, All } from 'ts-toolbelt';
// Check if all types in a list extend a certain constraint
type Valid = All<[string, number], any>;
// Requires understanding of variadic tuples and conditional types
Despite their differences, both libraries share some common goals and features.
// ts-essentials
import { DeepNullable } from 'ts-essentials';
type A = DeepNullable<{ a: { b: string } }>;
// ts-toolbelt
import { Object } from 'ts-toolbelt';
type B = Object.Optional<{ a: { b: string } }, 'deep'>;
// Both work with template literals
// ts-essentials: Uses them internally for key manipulation
// ts-toolbelt: Exposes them for string parsing utilities
// Importing these types adds 0 bytes to your final JS bundle
import { DeepPartial } from 'ts-essentials';
import { List } from 'ts-toolbelt';
| Feature | ts-essentials | ts-toolbelt |
|---|---|---|
| Philosophy | π― Focused, common use cases | π Exhaustive, all-encompassing |
| API Size | π¦ Small (~20 types) | π Massive (300+ types) |
| Learning Curve | π’ Easy, intuitive | π΄ Steep, requires type theory |
| Primitive Ops | β Not supported | β Numbers, Strings, Booleans |
| Best For | π’ App development, teams | π§ͺ Library authors, complex generics |
| Maintenance | π‘οΈ Stable, low risk | βοΈ Powerful, higher complexity |
ts-essentials is like a Swiss Army knife π¨πβit has the few tools you actually need every day, and they work perfectly. Choose it for standard application development where clarity and stability matter most. It solves the "I need DeepPartial again" problem without dragging in a massive dependency.
ts-toolbelt is like a fully equipped machine shop πβit has every tool imaginable, including some you didn't know existed. Choose it when you are building complex abstractions, validating intricate data shapes, or pushing the limits of what TypeScript can do at the type level.
Final Thought: For most frontend teams, ts-essentials will cover 95% of needs with less friction. Reserve ts-toolbelt for those specialized cases where you truly need to perform type-level magic that no other library can handle.
Choose ts-essentials if your team needs a reliable, stable set of utility types for everyday application development without the overhead of a massive dependency. It is ideal for projects that require common transformations like making nested objects partial or extracting specific property values, where code readability and long-term maintenance are priorities. This package is the best fit when you want to solve 90% of type manipulation problems with a well-documented, focused API that rarely breaks across TypeScript versions.
Choose ts-toolbelt if you are building complex generic libraries, performing advanced type-level logic, or need specific utilities for manipulating tuples, numbers, or strings that do not exist in other packages. It is suitable for scenarios where you need an exhaustive toolbox and are comfortable navigating a vast API surface to find niche solutions. Opt for this when your type requirements go beyond standard object manipulation and demand deep, recursive, or mathematical type operations that standard TypeScript cannot handle natively.
All essential TypeScript types in one place π€
npm install --save-dev ts-essentials
π We require typescript>=4.5. If you're looking for support for older TS versions, please have a look at the
TypeScript dependency table
π As we really want types to be stricter, we require enabled strictNullChecks in your project
ts-essentials is a set of high-quality, useful TypeScript types that make writing type-safe code easier.
Builtin - Matches primitive, function, date, error or regular expressionJsonArray - Matches any JSON arrayJsonObject - Matches any JSON objectJsonPrimitive - Matches any
JSON primitive valueJsonValue - Matches any JSON valueKeyofBase -
keyofStringsOnly-tolerant analogue for PropertyKeyPrettify<Type> - flattens type and makes it more readable on the hover in your IDEPrimitive - Matches any
primitive valueStrictExclude<UnionType, ExcludedMembers> - Constructs a type by excluding from UnionType
all union members that are assignable to ExcludedMembers. This is stricter version of
ExcludeStrictExtract<Type, Union> - Constructs a type by extracting from Type all union members
that are assignable to Union. This is stricter version of
ExtractStrictOmit<Type, Keys> - Constructs a type by picking all properties from Type and then
removing Keys. This is stricter version of
OmitWritable<Type> - Constructs a type with removed readonly for all properties of Type, meaning
the properties of the constructed type can be reassignedAsyncOrSync<Type> - Constructs a type with Type or PromiseLike<Type>AsyncOrSyncType<Type> - Unwraps AsyncOrSync typeDictionary<Type, Keys?> - Constructs a required object type which property keys are Keys
(string by default) and which property values are TypeMerge<Object1, Object2> - Constructs a type by picking all properties from Object1 and Object2.
Property values from Object2 override property values from Object1 when property keys are the sameMergeN<Tuple> - Constructs a type by merging objects with type Merge in tuple Tuple recursivelyNewable<ReturnType> - Constructs a class type with constructor which has return type ReturnTypeOmitNeverProperties<Type> - Constructs a type by picking all properties from type Type, which values don't
equal to neverOmitProperties<Type, Value> - Constructs a type by picking all properties from type Type
and removing those properties which values equal to ValueOpaque<Type, Token> - Constructs a type which is a subset of Type with a specified unique token
TokenPathValue<Type, Path> - Constructs a path value for type Type and path PathPaths<Type> - Constructs a union type by picking all possible paths for type TypePickProperties<Type, Value> - Constructs a type by picking all properties from type Type
which values equal to ValuePublicInterface<Type> - Constructs a type by extracting only the public members of Type, producing a plain object-compatible interfaceRequireAtLeastOne<Type, Keys?> - Constructs a type with at least one required key from Keys (keyof Type by default) and other keys from Type which are not part of KeysRequireAtMostOne<Type, Keys?> - Constructs a type with at most one required key from Keys (keyof Type by default) and other keys from Type which are not part of KeysSafeDictionary<Type, Keys?> - Constructs an optional object type which property keys are
Keys (string by default) and which property values are TypeUnionToIntersection<Union> - Constructs a intersection type from union type UnionValueOf<Type> - Constructs a type for type Type and equals to a primitive for primitives, array
elements for arrays, function return type for functions or object property values for objectsXOR<Type1, Type2, Type3?, ..., Type50?> - Construct a type which is assignable to either type Type1,
Type2 but not both. Starting in ts-essentials@10, it supports up to 50 generic types.MarkOptional<Type, Keys> - Constructs a type by picking all properties from type Type where
properties Keys are set as optional, meaning they aren't requiredMarkReadonly<Type, Keys> - Constructs a type by picking all properties from type Type where
properties Keys are set to readonly, meaning they cannot be reassignedMarkRequired<Type, Keys> - Constructs a type by picking all properties from type Type where
properties Keys are set as requiredMarkWritable<Type, Keys> - Constructs a type by picking all properties from type Type where
properties Keys remove readonly modifier, meaning they can be reassignedBuildable<Type> - Constructs a type by combining DeepPartial and DeepWritable, meaning all
properties from type Type are recursively set as non-readonly and optional, meaning they can be reassigned and
aren't requiredDeepMarkOptional<Type, KeyPathUnion> - Constructs a type by picking all properties from type Type where
properties by paths KeyPathUnion are set as optional. To mark properties optional on one level, use MarkOptional<Type, Keys>.DeepMarkRequired<Type, KeyPathUnion> - Constructs a type by picking all properties from type Type where
properties by paths KeyPathUnion are set as required. To mark properties required on one level, use MarkRequired<Type, Keys>.DeepNonNullable<Type> - Constructs a type by picking all properties from type Type
recursively and exclude null and undefined property values from all of them. To make properties non-nullable on
one level, use NonNullable<Type>DeepNullable<Type> - Constructs a type by picking all properties from type Type recursively
and include null property values for all of themDeepOmit<Type, Filter> - Constructs a type by picking all properties from type Type and removing
properties which values are never or true in type Filter. If you'd like type Filter to be validated against a
structure of Type, please use StrictDeepOmit<Type, Filter>.DeepPartial<Type> - Constructs a type by picking all properties from type Type recursively
and setting them as optional, meaning they aren't required. To make properties optional on one level, use
Partial<Type>DeepPick<Type, Filter> - Constructs a type by picking set of properties, which have property
values never or true in type Filter, from type Type. If you'd like type Filter to be validated against a
structure of Type, please use StrictDeepPick<Type, Filter>.DeepReadonly<Type, OverrideDeepReadonlyOptions?> - Constructs a type by picking all properties from type Type recursively
and setting readonly modifier, meaning they cannot be reassigned. To make properties readonly on one level, use
Readonly<Type>DeepRequired<Type> - Constructs a type by picking all properties from type Type recursively
and setting as required. To make properties required on one level, use
Required<Type>DeepUndefinable<Type> - Constructs a type by picking all properties from type Type
recursively and include undefined property values for all of themDeepWritable<Type> - Constructs a type by picking all properties from type Type recursively
and removing readonly modifier, meaning they can be reassigned. To make properties writable on one level, use
Writable<Type>StrictDeepOmit<Type, Filter> - Constructs a type by picking all properties from type Type
and removing properties which values are never or true in type Filter. The type Filter is validated against a
structure of Type.StrictDeepPick<Type, Filter> - Constructs a type by picking set of properties, which have
property values never or true in type Filter, from type Type. The type Filter is validated against a
structure of Type.OptionalKeys<Type> - Constructs a union type by picking all optional properties of object type
TypePickKeys<Type, Value> - Constructs a union type by picking all properties of object type Type
which values are assignable to type ValueReadonlyKeys<Type> - Constructs a union type by picking all readonly properties of object
type Type, meaning their values cannot be reassignedRequiredKeys<Type> - Constructs a union type by picking all required properties of object type
TypeUnionKeys<UnionType> - Constructs a union type by picking all properties from all union members of UnionTypeWritableKeys<Type> - Constructs a union type by picking all writable properties of object type
Type, meaning their values can be reassignedIsAny<Type> - Returns true when type Type is any. Otherwise returns falseIsExact<Type, Shape> - Returns Type when type Type and Shape are identical. Otherwise returns
neverIsNever<Type> - Returns true when type Type is never. Otherwise returns falseIsUnknown<Type> - Returns true when type Type is unknown. Otherwise returns falseIsTuple<Type> - Returns Type when type Type is tuple. Otherwise returns neverNonEmptyObject<Object> - Returns Object when Object has at least one key. Otherwise
returns neverNonUnion<Type> - Returns Type when Type is not an union. Otherwise returns neverAnyArray<Type?> - Matches Array or ReadonlyArray (Type is any by default)AnyNonEmptyArray<Type> - Matches array with at least one element of type TypeArrayOrSingle<Type> - Matches Type or Type[]ElementOf<Type> - Constructs a type which equals to array element type for type TypeHead<Type> - Constructs a type which equals to first element in type TypeReadonlyArrayOrSingle - Matches Type or readonly Type[]Tail<Type> - Constructs a type which equals to elements but first one in type TypeTuple<Type?> - Matches type constraint for tuple with elements of type Type (any by default)CamelCase<Type> - Converts type Type to camel case (e.g. camelCase)DeepCamelCaseProperties<Type> - Constructs a type by picking all properties from
type Type recursively and converting all of them to camel caseAnyFunction<Args?, ReturnType?> - Matches function type with arguments type Args (any[] by
default) and return type ReturnType (any by default)PredicateFunction - Matches type constraint for type guard, meaning first argument is
used in return type and return type is
type predicatePredicateType<Type> - Constructs a type which equals to narrowed type in predicate function
Typeβ οΈ Make sure you add ts-essentials to your dependencies (npm install --save ts-essentials) to avoid runtime errors
new UnreachableCaseError(value) - Matches runtime class instance type that
helps check exhaustiveness for value. When value isn't never, it shows TypeScript errorassert(condition, message?) - Matches runtime function that helps assert condition. When
condition is falsy, it throws an error with Assertion Error: ${message} (message is
"no additional info provided" by default)createFactoryWithConstraint<Constraint>()(value) - Matches runtime
function, which validates that type of value matches Constraint without changing resulting type of value.
Ponyfill for
satisfies operatorisExact<Expected>()(actual) - Matches runtime function, which validates that type of
actual equals to Expected. Otherwise shows TypeScript errornoop(..._args) - Matches runtime function that does nothing with arguments _argsWhen one of utility types is known by a different name, kindly ask adding it here for the better search.
ArrayValues - ValueOf<Type>Branded - Opaque<Type, Token>ConditionalKeys - PickKeys<Type, Value>Except - StrictOmit<Type, Keys>Get - PathValue<Type, Path>Mutable - Writable<Type>Nominal - Opaque<Type, Token>Set*, e.g. SetOptional - Mark*, e.g. MarkReadonly<Type, Keys>Unwrap - Prettify<Type>ValueOf - DictionaryValuesArray.includes - Use ts-reset instead. See compromises in Array.includes as a type guardBoolean as a type guard in Array.filter - Use ts-reset instead.TypeScript provides several utility types to facilitate common type transformations. These utilities are available globally.
Awaited<Type> - This type is meant to
model operations like await in async functions, or the .then() method on Promises - specifically, the way that
they recursively unwrap PromisesCapitalize<StringType> -
Converts the first character in the string to an uppercase equivalentConstructorParameters<Type> -
Constructs a tuple or array type from the types of a constructor function type TypeExclude<UnionType, ExcludedMembers> -
Constructs a type by excluding from UnionType all union members that are assignable to ExcludedMembersExtract<Type, Union> -
Constructs a type by extracting from Type all union members that are assignable to UnionInstanceType<Type> - Constructs
a type consisting of the instance type of a constructor function in TypeLowercase<StringType> -
Converts each character in the string to the lowercase equivalentNonNullable<Type> - Constructs a
type by excluding null and undefined from TypeNoInfer<Type> - Blocks inferences to the contained type. Other than blocking inferences, NoInfer<Type> is identical to TypeOmit<Type, Keys> - Constructs a
type by picking all properties from Type and then removing KeysOmitThisParameter<Type> - Removes the this parameter from Type. If Type has no explicitly declared this parameter, the result is simply Type. Otherwise, a new function type with no this parameter is created from Type. Generics are erased and only the last overload signature is propagated into the new function type.Parameters<Type> - Constructs a
tuple type from the types used in the parameters of a function type TypePartial<Type> - Constructs a type
with all properties of Type set to optionalPick<Type, Keys> - Constructs a
type by picking the set of properties Keys from TypeReadonly<Type> - Constructs a type
with all properties of Type set to readonly, meaning the properties of the constructed type cannot be reassignedRecord<Keys, Type> - Constructs
an object type whose property keys are Keys and whose property values are TypeRequired<Type> - Constructs a type
consisting of all properties of Type set to requiredReturnType<Type> - Constructs a
type consisting of the return type of function type Type parameterThisParameterType<Type> - Extracts the type of the this parameter for a function type, or unknown if the function type has no this parameterThisType<Type> - This utility does not return a transformed type. Instead, it serves as a marker for a contextual this type. Note that the noImplicitThis flag must be enabled to use this utilityUncapitalize<StringType> -
Converts the first character in the string to a lowercase equivalentUppercase<StringType> -
Converts each character in the string to the uppercase versionts-essentials | typescript / type of dependency |
|---|---|
^10.0.0 | ^4.5.0 / peer optional |
^9.4.0 | ^4.1.0 / peer optional |
^8.0.0 | ^4.1.0 / peer |
^5.0.0 | ^3.7.0 / peer |
^3.0.1 | ^3.5.0 / peer |
^1.0.1 | ^3.2.2 / dev |
^1.0.0 | ^3.0.3 / dev |
extends Constraints on infer Type Variables as it's introduced in TypeScript 4.7, but currently ts-essentials supports versions below, e.g. TypeScript 4.5. Read more in https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#extends-constraints-on-infer-type-variablesSpecial shout-out to active contributors:
And thanks goes to these wonderful people:
π» - contributions, i.e. links to commits by the user on this project
Contributions of any kind welcome! Read more