TypeScript Exclude and Extract
Exclude and Extract are built-in utility types that operate on Union Types. They allow you to filter unions by either removing specific members or keeping only specific members.
1. Exclude<UnionType, ExcludedMembers>
Exclude constructs a type by excluding from UnionType all union members that are assignable to ExcludedMembers.
- Mental Model: "Remove these specific types from the list."
Basic Example
type Status = "success" | "warning" | "error" | "info";
// Remove "warning" and "info"
type CriticalStatus = Exclude<Status, "warning" | "info">;
// type CriticalStatus = "success" | "error"
Removing null and undefined
While NonNullable is usually preferred, Exclude can also do this.
type MaybeString = string | number | null | undefined;
type JustValues = Exclude<MaybeString, null | undefined>;
// type JustValues = string | number
Excluding Shapes
You can exclude types based on shape compatibility.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number }
| { kind: "triangle"; base: number };
// Remove the circle
type AngularShapes = Exclude<Shape, { kind: "circle" }>;
// type AngularShapes = { kind: "square"... } | { kind: "triangle"... }
2. Extract<Type, Union>
Extract is the opposite of Exclude. It constructs a type by extracting from Type all union members that are assignable to Union.
- Mental Model: "Keep only these types from the list." (Intersection of two unions).
Basic Example
type Status = "success" | "warning" | "error" | "info";
// Keep only "error" and "warning"
type BadStatus = Extract<Status, "error" | "warning">;
// type BadStatus = "warning" | "error"
Finding Common Types
If you have two unions, Extract finds the overlap.
type A = "a" | "b" | "c";
type B = "b" | "c" | "d";
type Common = Extract<A, B>;
// type Common = "b" | "c"
3. How they work
Both utilities rely on Distributive Conditional Types.
// Exclude implementation
type Exclude<T, U> = T extends U ? never : T;
// Extract implementation
type Extract<T, U> = T extends U ? T : never;
When T is a union (e.g., "a" | "b"), TypeScript distributes the condition:
- Is
"a"assignable toU? - Is
"b"assignable toU?
If the result is never, that member is removed from the final union.
programming/javascript/typescript/typescript programming/javascript/typescript/utility-types programming/javascript/typescript/conditional-types