# TypeScript Type Challenge Exclude Walkthrough

The goal of the challenge is to implement a generic type MyExclude that works the same way the built in Exclude type works, without using `Exclude`

The challenge: https://github.com/type-challenges/type-challenges/blob/main/questions/00043-easy-exclude/README.md

## Watch the video

## An example case

For example, given the following cases, our MyExclude type should return the type shown in the comments:

` MyExclude<'a' | 'b' | 'c', 'a'> // 'b' | 'c'`

MyExclude<'a' | 'b' | 'c', 'a' | 'b'> // 'c'

MyExclude<string | number | (() => void), Function> // string | number

## Approach

In plain english, we want our type to:

loop over everything in

`T`

, if it doesn't exist in`U`

include it in our new type

On paper, this sounds very similar to our approach for implementing our own Pick type, and a naive approach might look something like:

`type MyExclude<T extends (string | number | symbol), U> = {`

[Property in T]: Property extends U ? never : Property

}

Where we loop over everything in `T`

using a mapped type, and then use a conditional type to either exclude it (returning `never`

) or include it (returning `Property`

).

This solution partially works, but results in a type (for our first example case) of:

` MyExclude<'a' | 'b' | 'c', 'a'> // { a: never, b: 'b', c: 'c'}`

This is along the right lines, and could probably be coerced into the expected shape, but misses the point of this challenge.

To solve this we need to know one of the "super powers" of conditional types in TypeScript, that is they are distributive over unions. What does that mean?

This means when a conditional type is working on a union type, (`T extends something`

where T is a union type), then the condition is applied to each member of that union.

For example,

`type YesOrNo<T extends boolean> = T extends true ? "yes" : "no"`

When we call that type with one value:

`YesOrNo<true> // "yes"`

We get back the single type "yes", but when we call it with a union type:

`YesOrNo<true | false> // "yes" | "no"`

We get back a union type, where each element in the union has been applied to the type.

## The solution

So the solution to our `MyExclude`

problem actually becomes very simple:

` type MyExclude<T, U> = T extends U ? never : T`

We use a conditional type `T extends U`

to check if `T`

exists in `U`

, if it does, we return `never`

, otherwise we include it in the resulting object. Returning `never`

works to exclude items, as `never`

gets dropped by union types that include it.