Everyday TypeScript: Partial
Welcome to the Partial lesson!
This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!
Sometimes we need a flexible way to create "partial" objects. These are objects with some of an object type's properties, but not necessarily all of them. We could do that manually with the
?syntax for optional properties.>
type User = {name: stringphoneNumber: string};type PartialUser = {name?: stringphoneNumber?: string};This works, but it's not a good solution. First, it's verbose because we have to define two duplicate versions of the type. Second, it can lead to difficult bugs if the
UserandPartialUsertypes ever go out of sync. We might change a property's type inUser, but forget to make the corresponding change inPartialUser.Fortunately, TypeScript provides a generic utility type for this:
Partial. The typePartial<T>means "an object that has the same properties asT, but each property is optional". It's as if we'd defined a new copy of the type, but given every property a?, likename?: string.Here's a partial user type again. This time we use
Partial<User>instead of defining the entirePartialUsertype manually.>
type User = {name: stringpostalCode: string};const partialAmir: Partial<User> = {postalCode: '75010'};partialAmir.postalCode;Result:
'75010'
In that example,
Partial<User>is exactly the same type as{name?: string, postalCode?: string}.When we access the properties in a partial object type, we get a union with
undefined. For example, thepostalCodeproperty above is astring | undefined. As usual, we'll get a type error if we try to use it without considering theundefinedcase.>
type User = {name: stringpostalCode: string};const partialAmir: Partial<User> = {postalCode: '75010'};const postalCode: string = partialAmir.postalCode;Result:
type error: Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'.
Here's a code problem:
In the code below, we want to build a partial
Albumobject. Currently, we're getting a type error because some of the album's properties are missing. Use thePartialtype to fix the type error, but don't change any of the object's properties.type Album = {name: stringcopiesSold: number};const kindOfBlue: Partial<Album> = {name: 'Kind of Blue',};kindOfBlue;- Goal:
{name: 'Kind of Blue'}- Yours:
{name: 'Kind of Blue'}
Finally, let's look at the type definition for
Partialitself. We found this type in the file "node_modules/typescript/lib/lib.es5.d.ts".Partialis a mapped type, which is a TypeScript feature that you may not have seen yet, so don't worry if that part is unfamiliar. However, the?in[P in keyof T]?: T[P]should look familiar! It's the same?that we've seen in types like{name?: string}.>
type Partial<T> = {[P in keyof T]?: T[P];};This shows that we could write
Partialourselves if we wanted to, just like all of the other utility types!