Back to all posts

Partially match a subset of an object's fields in Typescript

I have a type Contact that gets used in multiple places. A Person can have a contact, so it becomes a field on their type, but also a Company can have a contact.

export interface Contact {
  firstName: string
  lastName: string
  phoneNumber: string
}
 
export type Person = {
  id: string
  contact: Contact
}
 
export type Company = {
  id: string
  contact: Contact
}
const company = {
  id: uuid(),
  contact: {
    phoneNumber: "+123456790",
  },
}

produces the error

Type '{ phoneNumber: string; }' is missing the following properties from type 'Contact': firstName, lastName

Typescript expects that all implementations of the Contact type use every defined field, but since a business doesn't need to have a first or last name, I don't want to have to add those.

The solution

There are several typescripty ways to solve this

New type

One solution is to stop messing around with reusability and just make a new type for this clearly different use-case.

export interface CompanyContact {
  phoneNumber: string
}
 
export type Company = {
  id: string
  contact: CompanyContact
}

Partial

The Partial type makes every field optional

export type Company = {
  id: string
  contact: Partial<Contact>
}

Pick

Pick allows you to pick specifically which fields you want

export type Company = {
  id: string
  contact: Pick<Contact, "phoneNumber">
}