Type subsets with TypeScript Partials

The Partial type is one of the utility types in TypeScript. You can use the Partial type to represent a subsets of the type variable you pass to it.

In an application that communicates with a REST API you ofter find yourself writing interfaces to represent a resource you want to create. If you’re about to create a new user your interface might look similar to the one below.

interface User {
  firstName: string;
  lastName: string;
  email: string;
}

If you have all the required properties and pass them in a function that expects a User TypeScript is happy and won’t complain.

function createUser(user: User) {
  // ...
}

const user: User = {
  firstName: 'Winston',
  lastName: 'Tortoise',
  email: 'w.tortoise@example.com'
}

createUser(user);

But now that you have sir Winston in your database and he decides to change his email address. You can’t just pass the update for a single property into a function that expects a parameter of type User. TypeScript won’t be happy and will complain.

function updateUser(user: User) {
  // ...
}

const newMail = 'winston.tortoise@example.com'

updateUser({ email: newMail }) // TypeScript says NO!

So how to solve this. Instead of creating a second interface to represent a specific user update you could give Partial a try. With the Partial utility type you create a new type from an already existing one but makes all the properties optional. To make this a bit more visual, see the snipper below of how the Partial type is defined in TypeScript.

/**
 * Make all properties in T optional
 */
type Partial<T> = {
  [P in keyof T]?: T[P];
};

So to make TypeScript happy we use the Partial utility type with User as its generic. By doing this the updateUser will only accept an object with properties in the User type. Take note that all the properties are made optional, so even an empty object will be fine in this case.

function updateUser(user: Partial<User>) {
  // ...
}

const newMail = 'winston.tortoise@example.com'

updateUser({ email: newMail }) // TypeScript is happy

Require one property in partial

Having all the fields optional is in some cases not what you want. For example, sometimes all the fields can be optional expect for an unique identifier you need to identify a specific user. This might not not be the most elegant solution but you could solve this by combining a partial with the Pick utility type. The Pick type requires a subset of properties in a type. See the snippet below of how the Pick type is implemented in TypeScript.

/**
 * From T, pick a set of properties whose keys are in the union K
 */
type Pick<T, K extends keyof T> = {
  [P in K]: T[P];
};

In the example below shows how to combine Pick with Partial to make all properties of User optional except for the email property.

function updateUser(user: Pick<Partial<User>, 'email'>) {
  // ...
}

// TypeScript says NO :(
updateUser({ firstName: 'Hannah' })

// TypeScript says Yes! :)
updateUser({ firstName: 'Hannah', email: 'hannah@example.com'})

List of partials

Partials can be used with as a list too. By adding a [] after the Partial type TypeScript will expect an array of partials. The items in the array of partials don’t need to have the same properties. So TypeScript is 100% fine with the example below.

const users: Partial<User>[] = [
  {firstName: "John"}, // First user
  {lastName: "James"}, // Second user
];

See Also

6 Non-Programming Books for Programmers