Menu

TypeScript Exclude, Extract and NonNullable Explained

Exclude, Extract and NonNullable filter the members of a union type. Learn what each keeps and removes, how to pick union members by shape, how they are built from conditional types, and how they differ from Omit and Pick.

This page includes runnable editors - edit, run, and see output instantly.

Exclude<T, U> removes members from a union type, Extract<T, U> keeps only the matching members, and NonNullable<T> removes null and undefined. All three filter unions; they do not touch object properties.

Like every utility type, these exist only at compile time. The last line is rejected by the compiler; the JavaScript that runs has no idea what Visible is.

Exclude, Extract and NonNullable at a Glance

TypeKeepsExampleResult
Exclude<T, U>members of T not assignable to UExclude<"a" | "b" | "c", "a">"b" | "c"
Extract<T, U>members of T assignable to UExtract<"a" | "b" | "c", "a" | "z">"a"
NonNullable<T>everything except null and undefinedNonNullable<string | null | undefined>string

"Assignable to U" is the key phrase. U does not have to be a list of exact members; it can be a wider type that several members fit:

Picking Union Members by Shape

On a discriminated union, Extract with a partial shape pulls out the variants that have it. This is the usual way to name one variant of a union you did not write yourself:

The shape { type: "click" } is a supertype of the click variant only, so that is the one Extract keeps. A shape that matches several variants (say { x: number } if two had it) keeps all of them.

NonNullable

NonNullable<T> is the type version of a !== null && !== undefined check. It shows up when you derive a type from something optional:

User["manager"] is { name: string } | null | undefined (the ? adds undefined), and NonNullable strips both. Since TypeScript 5.5 the compiler also infers that predicate by itself, so raw.filter((s) => s != null) is already typed string[]; the explicit s is NonNullable<typeof s> keeps the intent visible and works in older versions. Its definition is type NonNullable<T> = T & {}: the empty object type {} accepts every value except null and undefined, so intersecting with it removes exactly those.

How They Are Built

Exclude and Extract are one-line conditional types in the standard library:

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

When T is a union, a conditional type is applied to each member separately (it distributes), and never members vanish from the result. So Exclude<"a" | "b", "a"> becomes ("a" extends "a" ? never : "a") | ("b" extends "a" ? never : "b"), which is never | "b", which is "b". The conditional types page covers distribution in detail.

Exclude vs Omit, Extract vs Pick

The names are easy to mix up because both pairs "remove" or "keep" something. The difference is what they operate on:

Works onRemoves or keepsExample
Exclude<T, U>a unionunion membersExclude<"a" | "b", "a"> → "b"
Extract<T, U>a unionunion membersExtract<"a" | "b", "a"> → "a"
Omit<T, K>an object typepropertiesOmit<User, "password">
Pick<T, K>an object typepropertiesPick<User, "name">

Using Exclude on an object type is a common slip, and it fails silently:

Account is not assignable to "password", so Exclude keeps it whole. Omit itself is built from Exclude applied to the keys: Omit<T, K> is Pick<T, Exclude<keyof T, K>>. See Omit for more.

A Stricter Exclude

Exclude's second parameter accepts any type, so a typo removes nothing and raises no error. Adding a constraint makes the compiler check that what you exclude is really in the union:

index.ts(7,37): error TS2344: Type '"drafft"' does not satisfy the constraint 'Status'.

Fix the spelling and it compiles, with Strict equal to "published" | "archived". The same trick works for Extract and for a strict Omit (K extends keyof T).

Frequently Asked Questions

What does Exclude do in TypeScript?

Exclude<T, U> removes from the union T every member that is assignable to U. Exclude<"a" | "b" | "c", "a"> is "b" | "c". To remove several members, pass a union as U: Exclude<T, "a" | "b">.

What is the difference between Exclude and Extract?

They are opposites. Exclude<T, U> keeps the members of T that are not assignable to U; Extract<T, U> keeps only the members that are. For the same T and U, the two results together make up T.

What is the difference between Exclude and Omit?

Exclude works on a union type and removes union members. Omit works on an object type and removes properties. Exclude<User, "password"> does nothing useful (it returns User), while Omit<User, "password"> gives the object type without that property. Omit is built on Exclude: it excludes the key from keyof T.

What does NonNullable do in TypeScript?

NonNullable<T> removes null and undefined from a type: NonNullable<string | null | undefined> is string. It is defined as T & {}, since {} accepts every value except null and undefined.

Why does Exclude not report an error for a member that does not exist?

Its second parameter is unconstrained, so any type is accepted, and a typo such as Exclude<Status, "drafft"> silently removes nothing. Define a stricter version, type StrictExclude<T, U extends T> = Exclude<T, U>, to make the compiler check that U is part of T.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED