NonNullable<Type>

Removes null and undefined from a type, leaving only its definitely-present members.

Signature
type NonNullable<Type> = Type & {}
  • Added in TypeScript 2.8

Parameters

ParameterTypeDescription
$Typeany typeThe type to strip nullish members from. Under `strictNullChecks: false` this is a no-op, because null and undefined are already absent from every union.

Return value

Type with null and undefined removedThe intersection of Type with the empty object type, which reduces away `null` and `undefined` because neither is assignable to `{}`.

Errors

Nothing at runtime. The checker errors when a nullish value is assigned to the resulting type.

Changelog

  • PHP 4.8Reimplemented from the conditional `Type extends null | undefined ? never : Type` to the intersection `Type & {}`. Intersections reduce and can be assigned to where conditional types cannot, so nested applications now simplify — but `NonNullable<unknown>` is now `{}` rather than `unknown`.

NonNullable strips null and undefined. Since TypeScript 4.8 it is implemented as Type & {}: nothing in JavaScript is both null and an object, and nothing is both undefined and an object, so those members reduce away while every other member survives the intersection unchanged.

It only does anything under strictNullChecks

With strictNullChecks: false, null and undefined are assignable to every type and are not tracked in unions, so there is nothing for NonNullable to remove — it is a no-op, and code that relies on it for safety has none. This is the first thing to check when the type looks right but a Cannot read properties of undefined still reaches production.

When to reach for it

  • Naming the payload type of an optional field: NonNullable<Response["data"]>.
  • Writing the return type of a filter predicate: (v): v is NonNullable<T> => v != null.
  • Composing inside a mapped type to strip nullishness from every property at once.

What trips people up

It does not filter values. The type says the nulls are gone; only a runtime filter actually removes them, and Array.prototype.filter will not narrow the element type unless you give it a type predicate.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Give a name to the non-null payload type of an optional API response field.
  • Write a `.filter()` type predicate that narrows `(T | null)[]` down to `T[]`.
  • Strip nullishness from every property of a type inside a mapped type.

Frequently asked questions

How do I remove null and undefined from a type?

Wrap it in `NonNullable<T>`, which since TypeScript 4.8 is implemented as `T & {}` — the intersection eliminates `null` and `undefined` because neither is assignable to `{}`.

Why does NonNullable seem to do nothing?

Almost always because `strictNullChecks` is off. Without it, `null` and `undefined` are assignable everywhere and never appear in unions, so there is nothing to strip. Turn on `strict` or `strictNullChecks` in tsconfig.json.

How do I filter nulls out of an array and get the narrowed type?

Give `.filter()` a type predicate: `items.filter((x): x is NonNullable<typeof x> => x != null)`. A plain `filter(Boolean)` removes the values at runtime but leaves the element type unchanged, and also drops `0` and `""`.

More examples

Naming the payload of an optional field

Prints `#a1: 12`, `no data (404)`, `#a2: 7`. `Payload` is derived rather than redeclared, so widening the `data` shape in the interface updates `render`'s parameter automatically. The `response.data ?` guard is still required — `NonNullable` describes the type after the check, it does not perform one.

Example · typescript
interface ApiResponse {
  status: number;
  data?: { id: string; total: number } | null;
  error?: string;
}

// One source of truth for the payload shape.
type Payload = NonNullable<ApiResponse["data"]>;

function render(payload: Payload): string {
  return `#${payload.id}: ${payload.total}`;
}

const responses: ApiResponse[] = [
  { status: 200, data: { id: "a1", total: 12 } },
  { status: 404, data: null },
  { status: 200, data: { id: "a2", total: 7 } },
];

for (const response of responses) {
  console.log(response.data ? render(response.data) : `no data (${response.status})`);
}

Stripping nullishness from every property

Prints `{ name: 'Ada', age: 36, nickname: 'AL' }` and then `null`. The mapped type combines two modifiers: `-?` removes the optional marker on `nickname`, and `NonNullable` removes the explicit `| null` from each property type. Neither alone is enough — `-?` does not touch a declared `null`, and `NonNullable` does not remove an optional marker.

Example · typescript
interface FormValues {
  name: string | null;
  age: number | null;
  nickname?: string | null;
}

type Submitted = { [K in keyof FormValues]-?: NonNullable<FormValues[K]> };
// Submitted is { name: string; age: number; nickname: string }

function validate(values: FormValues): Submitted | null {
  const { name, age, nickname } = values;
  if (name == null || age == null || nickname == null) return null;
  return { name, age, nickname };
}

console.log(validate({ name: "Ada", age: 36, nickname: "AL" }));
console.log(validate({ name: "Ada", age: null, nickname: "AL" }));

Discussion

  • Be the first to comment on this lesson.