DEV Community

Pragmatic Maciej
Pragmatic Maciej

Posted on

Advanced TypeScript Exercises - Answer 10

I've asked how to make different & operation by custom Merge type level function.

Note - if you don't recall what means - type level function please take a moment for reading - typescript is more than you think.

Solution 1 - Mapped Type

type Merge<A, B> = {
    [K in keyof A | keyof B]: 
        K extends keyof B ? B[K] : 
        K extends keyof A ? A[K] : never
}
Enter fullscreen mode Exit fullscreen mode

What we are doing here is creating function Merge which is a mapped type. Mapped type allows for iteration over one type and mapping it into another type.

  • [K in keyof A | keyof B] - we iterate over union of keys from both types A and B, union will remove repeating keys in both types, so iteration will not need to go through them twice
  • K extends keyof B ? B[K] : K extends keyof A ? A[K] : never - we use conditional type in order to check if our current key belongs to key of type B, if no, we check if it belongs to type A, if not belongs to any of these, what is not possible, we fallback to never.

Note pay attention that we check firstly B type, so if the key is in B, we take value from B, it means we will overwrite eventual value from type A. Don't worry though, that was the requirement of the task.

Note I said that there is no possibility that key will not be either in A or B, because we iterate over keyof A | keyof B, so there is no option that key will not belong to any of them.

Solution 2 - Using Omit

type Merge<A, B> = Omit<A, keyof B> & B; 
Enter fullscreen mode Exit fullscreen mode

Yes that is the whole solution 😉. TypeScript type level standard library gives us functions like Omit which is really just mapped type as we did in the solution 1. So if there is ready to use function why not to use it?

  • Omit<A, keyof B> we make type which contains only keys of A which are not in B
  • Omit<A, keyof B> & B - we merge B type to already created type which has no intersection with B as keys of B where removed from A.

In result we have done the same thing as in previous solution,but with one line of code.

Special thanks for SirMoustache, hnicolas and others for their great answers in comments. You can find both solution in the playground.

This series will continue. If you want to know about new exciting questions from advanced TypeScript please follow me on dev.to and twitter.

Top comments (1)

Collapse
 
nmonastyrskyi profile image
Nikita Monastyrskiy

Nice solutions, thanks!