TypeScript provides a feature known as utility types which help in common type transformations. These utilities help you manipulate types easily, making your applications more robust and maintainable. In this guide, we'll explore TypeScript's built-in utility types, focusing on how they can be leveraged to simplify and enhance your TypeScript code.
What are utility types?
Utility types are a set of generic types provided by TypeScript that perform certain operations on types. They are part of the TypeScript type system that helps in constructing new types based on existing ones, often to modify properties or extract information from them.
Commonly used TypeScript utility types
Here is an overview of some of the most commonly used utility types in TypeScript:
1. Partial<Type>
Converts all properties of a type to be optional. This is useful when you want to update only a few properties of an object.
interface User {id: numbername: stringage: number}type PartialUser = Partial<User>// All properties in PartialUser are optionalconst updateUser: PartialUser = { name: 'John' }
2. Required<Type>
Makes all properties of a type required, which is the opposite of Partial
.
interface Props {name?: stringage?: number}type RequiredProps = Required<Props>// All properties in RequiredProps are requiredconst props: RequiredProps = { name: 'John', age: 30 }
3. Readonly<Type>
Makes all properties of a type read-only, meaning you cannot reassign them after their initial declaration.
interface Task {title: string}type ReadonlyTask = Readonly<Task>const myTask: ReadonlyTask = { title: 'Write TypeScript Guide' }// myTask.title = "Update Guide"; // This line will throw an error
4. Record<Keys, Type>
Creates a type with a set of properties Keys
of a given type Type
. It’s useful for mapping properties to the same type.
type Status = 'active' | 'inactive' | 'pending'type StatusMessage = Record<Status, string>const statusMessage: StatusMessage = {active: 'User is active',inactive: 'User is inactive',pending: 'User registration is pending'}
For more info, see this comprehensive guide on the Record type.
5. Pick<Type, Keys>
Creates a type by picking the set of properties Keys
from Type
.
interface User {id: numbername: stringage: numberemail: string}type UserPreview = Pick<User, 'name' | 'email'>// UserPreview has only the name and email propertiesconst user: UserPreview = { name: 'John', email: 'john@example.com' }
For additional reading, see this comprehensive guide on the Pick type.
6. Omit<Type, Keys>
Creates a type by omitting the set of properties Keys
from Type
.
type UserSensitive = Omit<User, 'age'>// UserSensitive has id, name, and email, but not ageconst userSensitive: UserSensitive = {id: 1,name: 'John',email: 'john@example.com'}
For more examples, see this comprehensive guide on the Omit type.
7. Exclude<UnionType, ExcludedMembers>
Creates a type by excluding from UnionType
all union members that are assignable to ExcludedMembers
.
type T0 = Exclude<'a' | 'b' | 'c', 'a'> // "b" | "c"
8. Extract<Type, Union>
Creates a type by extracting from Type
all union members that are assignable to Union
.
type T1 = Extract<'a' | 'b' | 'c', 'a' | 'f'> // "a"
9. NonNullable<Type>
Creates a type by excluding null
and undefined
from Type
.
type T2 = NonNullable<string | number | undefined> // string | number
10. Parameters<Type>
Retrieves the parameter types of a function type in a tuple.
function greet(name: string, age: number): string {return `Hello ${name}, you are ${age} years old.`}type Params = Parameters<typeof greet> // [string, number]
For further reading on utility types see the official TypeScript documentation.