I remember that time I understood the concept of the High-Order Function. Until then I had limited myself to using the methods forEach
, map
, filter
, find
, etc. Then, one day, I no longer remember how or why, I found myself looking inside them - a bit like a curious person grappling with analog clock gears. I turned them over and over, peeling off and refitting pieces until their inner workings became clear.
In this post I propose to apply a similar approach on TypeScript's utility types.
First it is necessary to understand how to refer to one of the properties in an object - keyof
.
interface Hero {
hp: number;
sword: boolean;
shield: boolean;
};
const hero: Hero = {
hp: 42,
sword: true,
shield: false,
};
type HeroItem = keyof typeof hero; // "hp" | "sword" | "shield"
Note: if the hero was defined via a class, there would be no need for
typeof
.class Hero { ... } type heroItem = keyof Hero;
Now, we want to allow the hero to be able to upgrade.
interface Hero {
hp: number;
sword: boolean;
shield: boolean;
upgrade: (items: Partial<Hero>) => void;
};
const hero: Hero = {
hp: 42,
sword: true,
shield: false,
upgrade(items) {
Object.assign(this, items);
}
};
hero.upgrade({ shield: true });
Thanks to Partial<Hero>
, the items
parameter will make all the properties of the passed Hero
conditional.
Once you know how to read it, the functioning of Partial
is easy to grasp:
How it works?
- Take a type (
T
) on which to operate - The result is an object (
= { ... }
) - Each key should be dynamically assigned, hence the use of square brackets.
- Each key is optional, thus the
?
- The value must have the correct type; in the "key-side" we define a
P
(could be any letter or word) and use it to extrapolate the type from the subject type (T[P]
)
type myPartial = { [P in keyof T]?: T[P] }
Feel free to linger at it until all the various bits and pieces are clear to you.
I don't implement
Array.prototype.map
for each new project - I get smart and use built-in. UsePartial
.
Top comments (0)