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
π