beraliv

Spread in Object types

Example of Merge use
1type Merge<F, S> = any; // implementation
2
3type EmptyArticle = { title: "<title>"; description: "<description>" };
4type Article = { title: "TypeScript" };
5
6type Step1 = Merge<EmptyArticle, Article>;
7type Result = { title: "TypeScript"; description: "<description>" };

Today we discuss Merge

It's quite convenient to use it in combination with ES6 spread operator for objects.

Let's try it out 🚀

Iterate over object keys

As I previously said, EcmaScript 6 introduced the spread operator which does the same in JavaScript which we want to achieve here. Let's have an example:

Spread in JavaScript
1const emptyObject = {
2 title: "<title>",
3 description: "<description>",
4} as const;
5const article = { title: "TypeScript" } as const;
6
7// { title: "TypeScript", description: "<description>" }
8const result = { ...emptyObject, ...article };

If we have the same key in both objects, we use if from the second object. Otherwise, we get it from the first object.

So let's iterate over all keys of two objects in TypeScript and check whether we have a key in second object. If so, we extract value from the second object. Otherwise, we get value from the first object – https://tsplay.dev/Nl0BlN

Merge, version 1
1type Merge<F, S> = {
2 [K in keyof F | keyof S]: K extends keyof S ? S[K] : F[K];
3};

Unfortunately, we have an error when we use F[K] as TypeScript doesn't know in advance if K is a key of first object F. Let's add the condition explicitly:

Merge, final version
1type Merge<F, S> = {
2 [K in keyof F | keyof S]: K extends keyof S
3 ? S[K]
4 : K extends keyof F
5 ? F[K]
6 : never;
7};

This workaround works and that's actually the solution – https://tsplay.dev/wRpM7m

Thank you for your time and have a wonderful evening 🌇

typescript
Alexey Berezin profile image

Written by Alexey Berezin who loves London 🏴󠁧󠁢󠁥󠁮󠁧󠁿, players ⏯ and TypeScript 🦺 Follow me on Twitter