What is Exclude Type in TypeScript?

Hemanta Sundaray

Published December 30, 2023


Exclude is a distributive conditional type in TypeScript. It has the following syntax:

Exclude<UnionType, ExcludedMembers>;

The Exclude utility type constructs a new type by excluding from UnionType all union members that are assignable to ExcludedMembers.

Remember, I said that Exclude is a distributive conditional type. Let's understand what that means.

Conditional Types

A conditional type in TypeScript allows you to define a type based on a condition. It's similar to how you use if-else statements in regular programming.

The basic syntax is T extends U ? X : Y, which reads as "if type T extends (or can be assigned to) type U, then use type X, otherwise use type Y."

Distributive Conditional Types

When a conditional type is applied to a union type, TypeScript doesn't apply the condition to the union as a whole. Instead, it distributes the condition over each member of the union. This is known as a distributive conditional type.

Consider a union type A | B | C and a conditional type T extends U ? X : Y. When applied distributively, TypeScript evaluates this condition separately for A, B, and C. For each member of the union, TypeScript checks if that member extends U. If it does, X is included in the resulting type. If it doesn't, Y is included in the resulting type. The final type is a union of all these individual checks.

Now that you understand the concept of distributive conditional types, let's go through an example. This will solidify your understanding of the concept.

Exclude Type Example

Suppose we have a union type and we want to use Exclude to exclude certain types from it:

type UnionType = string | number | boolean | symbol;
 
type ExcludedType = Exclude<UnionType, number | boolean>; // ExcludeType becomes number | boolean.

Here, UnionType is a union of string, number, boolean, and symbol. We want to exclude only the number and boolean types from it using Exclude.

How Exclude works

Exclude<T, U> iterates over each member of T and checks if it is assignable to U. The syntax T extends U ? T : never is used internally.

Distribution over Union type

Iteration Over Each Member:

Conditional Check:

Combining Results:

The results are combined into a union: never | number | boolean | never.

Note

The never type acts as an exclusion marker. When a member of the union doesn't match the condition (extends U), it results in never, which is TypeScript's way of saying "this type will never occur here." In a union, never gets absorbed or ignored. The union never | number | boolean | never simplifies to just number | boolean.

Final result

The ExcludedType, in this case, becomes number | boolean. Only the types from UnionType that are assignable to number | boolean are included.