Read Anthropic’s case study about Graphite Reviewer

TypeScript utility types

Kenny DuMez
Kenny DuMez
Graphite software engineer

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.

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.

Here is an overview of some of the most commonly used utility types in TypeScript:

Converts all properties of a type to be optional. This is useful when you want to update only a few properties of an object.

Terminal
interface User {
id: number
name: string
age: number
}
type PartialUser = Partial<User>
// All properties in PartialUser are optional
const updateUser: PartialUser = { name: 'John' }

Makes all properties of a type required, which is the opposite of Partial.

Terminal
interface Props {
name?: string
age?: number
}
type RequiredProps = Required<Props>
// All properties in RequiredProps are required
const props: RequiredProps = { name: 'John', age: 30 }

Makes all properties of a type read-only, meaning you cannot reassign them after their initial declaration.

Terminal
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

Creates a type with a set of properties Keys of a given type Type. It’s useful for mapping properties to the same type.

Terminal
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.

Creates a type by picking the set of properties Keys from Type.

Terminal
interface User {
id: number
name: string
age: number
email: string
}
type UserPreview = Pick<User, 'name' | 'email'>
// UserPreview has only the name and email properties
const user: UserPreview = { name: 'John', email: 'john@example.com' }

For additional reading, see this comprehensive guide on the Pick type.

Creates a type by omitting the set of properties Keys from Type.

Terminal
type UserSensitive = Omit<User, 'age'>
// UserSensitive has id, name, and email, but not age
const userSensitive: UserSensitive = {
id: 1,
name: 'John',
email: 'john@example.com'
}

For more examples, see this comprehensive guide on the Omit type.

Creates a type by excluding from UnionType all union members that are assignable to ExcludedMembers.

Terminal
type T0 = Exclude<'a' | 'b' | 'c', 'a'> // "b" | "c"

Creates a type by extracting from Type all union members that are assignable to Union.

Terminal
type T1 = Extract<'a' | 'b' | 'c', 'a' | 'f'> // "a"

Creates a type by excluding null and undefined from Type.

Terminal
type T2 = NonNullable<string | number | undefined> // string | number

Retrieves the parameter types of a function type in a tuple.

Terminal
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.

Git inspired
Graphite's CLI and VS Code extension make working with Git effortless.
Learn more

Graphite
Git stacked on GitHub

Stacked pull requests are easier to read, easier to write, and easier to manage.
Teams that stack ship better software, faster.

Or install our CLI.
Product Screenshot 1
Product Screenshot 2