DEV Community

derek lawless
derek lawless

Posted on • Edited on • Originally published at dereklawless.ie

2

Partial Types in TypeScript

The Partial<T> utility type (added in TypeScript 2.1) allows you to take an existing type and make all of its properties optional. This can help in situations where you want to have some flexibility without removing strictness across the board.

Consider the following interface:

interface ChocolateBar {
    readonly manufacturer: string;
    readonly name: string;
    readonly price: Money;
}
~~~{% endraw %}

As specified, all properties of {% raw %}`ChocolateBar`{% endraw %} are required for the interface contract to be satisfied. (Incidentally, don't use the {% raw %}`Number` type for monetary values - [introduce a type](https://martinfowler.com/eaaCatalog/money.html).)

Inevitably, there will occasions where strictness like this can make life awkward. What if you want to be able to selectively update the values of a chocolate bar? Well, you might write something along the lines of:

~~~typescript
interface KeyValuePair {
    readonly key: string;
    readonly value: any;
}

const updateChocolateBar(bar: ChocolateBar, props: KeyValuePair[]): ChocolateBar {
    props.forEach(({ key, value }) => bar[key] = value);
    return bar;
}
~~~

While this may be sufficient, each `KeyValuePair` is ambiguous e.g. `{ "paws": 4 }` is perfectly valid. Ambiguous code is more difficult to reason about, test, and maintain.

A better approach is to use a Partial type:

~~~typescript
interface KeyValuePair {
    readonly key: string;
    readonly value: any;
}

const updateChocolateBar(bar: ChocolateBar, props: Partial<ChocolateBar>): ChocolateBar {
    return { ...bar, ...props };
}
~~~

Here, `Partial<ChocolateBar>` creates a type with all properties of `ChocolateBar` set to optional, effectively producing:

~~~typescript
interface ChocolateBar {
    readonly manufacturer?: string;
    readonly name?: string;
    readonly price?: Money;
}
~~~

Why is this approach superior?

1. The `ChocolateBar` contract is only altered for this _specific case_
1. `updateChocolateBar()` communicates its own contract more effectively, is less ambiguous in use, and straightforward to test
Enter fullscreen mode Exit fullscreen mode

Top comments (0)

typescript

11 Tips That Make You a Better Typescript Programmer

1 Think in {Set}

Type is an everyday concept to programmers, but it’s surprisingly difficult to define it succinctly. I find it helpful to use Set as a conceptual model instead.

#2 Understand declared type and narrowed type

One extremely powerful typescript feature is automatic type narrowing based on control flow. This means a variable has two types associated with it at any specific point of code location: a declaration type and a narrowed type.

#3 Use discriminated union instead of optional fields

...

Read the whole post now!