Hint
Exclude removes members from a union; Extract keeps only the matching members
Both work on union types to filter members based on a condition.
Exclude<T, U> — removes from T all types assignable to U:
type T = string | number | boolean | null | undefined;
type NonNullable<T> = Exclude<T, null | undefined>;
type Primitives = Exclude<T, null | undefined>;
// string | number | boolean
type StringOrNumber = Exclude<string | number | boolean, boolean>;
// string | number
Extract<T, U> — keeps from T only types assignable to U (opposite of Exclude):
type Strings = Extract<string | number | boolean, string | boolean>;
// string | boolean
// Practical use: filter union to only the callable types
type FnOnly = Extract<string | number | (() => void), Function>;
// () => void
Combined with discriminated unions:
type Action =
| { type: 'ADD'; payload: string }
| { type: 'REMOVE'; id: number }
| { type: 'CLEAR' };
// Extract only actions with a payload
type ActionWithPayload = Extract<Action, { payload: any }>;
// { type: 'ADD'; payload: string }
// Exclude the CLEAR action
type MutatingActions = Exclude<Action, { type: 'CLEAR' }>;
// { type: 'ADD'; payload: string } | { type: 'REMOVE'; id: number }
NonNullable<T> is just Exclude<T, null | undefined> built into TypeScript. Understanding Exclude lets you build your own specialized filters.