Alo
Alo

Alo

`Partial<Type>` in TypeScript

Photo by ClΓ©mence Bergougnoux on Unsplash

`Partial<Type>` in TypeScript

Alo's photo
Alo
Β·Apr 2, 2022Β·

3 min read

This article is part of the Serie: Typescript utility types in plain English

Let's start with one of the easiest utility types: Partial<Type>

Partial in a nutshell πŸ₯œ

Partial allows you to make the properties of a type optional.

type Road = {
    surface:  'Gravel'|'Asphalt'|'Cobblestone'
    widthInMeters: number,
    speedLimitInKmPerHour: number
}

type PartialRoad = Partial<Road>

/* This is equivalent to:
type PartialRoad = {
    surface:  'Gravel'|'Asphalt'|'Cobblestone'|undefined
    widthInMeters: number|undefined,
    speedLimitInKmPerHour: number|undefined
}

or

type PartialRoad = {
    surface?:  'Gravel'|'Asphalt'|'Cobblestone',
    widthInMeters?: number,
    speedLimitInKmPerHour?: number,
}
*/

Example ✍️

Let's examine two common cases for the Partial utility type.

CRUD API

Let's assume you are building a CRUD API.

In your application, you want to register users' information as well as their hobbies.

Your interfaces might look like this:

type User = {
    firstName: string,
    middleName?:string
    lastName:string,
    dateOfBirth: Date,
    hobbies: Hobby[]
}

enum Hobby{
    Kitesurfing,
    Paragliding,
    Reading,
    Sleeping,
    /* ... */
}

To update your profile as a user, you have written a updateMyProfile function.

Imagine that the updateMyProfile contains all the logic necessary to call the API, handle errors, alert the user, etc.

Now, let's say I've started to kitesurf and I want to add this to my hobby list:

    function updateMyProfile(user: User){
        /* handle the API call to update user */
        /* `user` argument has to have all the properties of the user object, even non modified ones*/
    }

    let me: User {
        firstName: 'Alo',
    /* More information */
        hobbies: [Hobby.Reading, Hobby.Paragliding],
    }

    updateMyProfile({hobbies: me.hobbies.concat([Hobby.Kitesurf])}) 
    // 🚨 Error! UpdateMyProfile expect a full User object!

The issue here is that you have to pass all the properties of the user.

If the user wishes to only update her/his first name, we still need to pass a full User object containing all her/his information, even her/his hobbies.

It would be a lot more convenient if you could pass only the updated properties.

We can use Partial

    function updateMyProfile(user: Partial<User>){
        /* handle the API call to update user */
        /* `user` argument has to have all the properties of the user object, even non modified ones*/
    }

    let me: User {
        firstName: 'Alo',
        /* More information */
        hobbies: [Hobby.Reading, Hobby.Paragliding],
    }

    updateMyProfile({hobbies: me.hobbies.concat([Hobby.Kitesurf])}) 
    // 🟒 We don't need to pass the whole User object!

Optional Configuration

Another useful scenario is when you wish to use default values, such as configuration options.

    type IceCreamOrder = {
        numberOfScoops: number
    }

    const DEFAULT_NUMBER_OF_SCOOPS = 3;

    function orderIceCream(order: Partial<IceCreamOrder>){
        let numberOfScoops = order?.numberOfScoops || DEFAULT_NUMBER_OF_SCOOPS;
    };

Conclusion ☝️

As you can see, utility types in Typescript are a very powerful tool worth diving into.

I will see you soon for the next article on TypeScript utility types in plain English πŸ‘‹

Β 
Share this