TypeScript Exclude<T, U> vs Extract<T, U> Explained

Learn the difference between Exclude and Extract utility types for filtering union types. Side-by-side comparison with practical examples.

Union Types

Detailed Explanation

Exclude<T, U> vs Extract<T, U>

These two utility types are complementary operations on union types. Exclude removes members; Extract keeps members.

Exclude<T, U>

Removes from T all union members that are assignable to U:

type T = "a" | "b" | "c" | "d";
type Result = Exclude<T, "a" | "c">;
// Result: "b" | "d"

Extract<T, U>

Keeps from T only union members that are assignable to U:

type T = "a" | "b" | "c" | "d";
type Result = Extract<T, "a" | "c">;
// Result: "a" | "c"

Side-by-Side Comparison

type AllEvents = "click" | "scroll" | "keypress" | "resize" | "load";
type MouseEvents = "click" | "scroll";

type NonMouseEvents = Exclude<AllEvents, MouseEvents>;
// "keypress" | "resize" | "load"

type OnlyMouseEvents = Extract<AllEvents, MouseEvents>;
// "click" | "scroll"

With Discriminated Unions

Extract is especially powerful with discriminated unions:

type Action =
  | { type: "ADD_TODO"; text: string }
  | { type: "TOGGLE_TODO"; id: number }
  | { type: "DELETE_TODO"; id: number };

type TodoIdActions = Extract<Action, { id: number }>;
// { type: "TOGGLE_TODO"; id: number } | { type: "DELETE_TODO"; id: number }

How They Work Internally

Both are implemented using conditional types:

type Exclude<T, U> = T extends U ? never : T;
type Extract<T, U> = T extends U ? T : never;

Use Case

Use Exclude when you need to narrow a union by removing specific members (e.g., removing error states from a status union). Use Extract when you want to filter a union to keep only members matching a shape (e.g., extracting actions with an id property).

Try It — TypeScript Utility Types

Open full tool