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>;
- UnionType: This is the original union type from which you want to exclude certain members.
- ExcludedMembers: These are the members (or a union of members) that you want to exclude from UnionType.
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:
- string is compared to number | boolean.
- number is compared to number | boolean.
- boolean is compared to number | boolean.
- symbol is compared to number | boolean.
Conditional Check:
- string extends number | boolean results in never (because string is neither number nor boolean).
- number extends number | boolean results in number.
- boolean extends number | boolean results in boolean.
- symbol extends number | boolean results in never.
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.