Suggest an editImprove this articleRefine the answer for “Utility type nonnullable in TypeScript”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`NonNullable<T>`** removes `null` and `undefined` from type `T`. ```typescript type MaybeId = string | null | undefined; type Id = NonNullable<MaybeId>; // string ``` **Key takeaway:** type-only, no runtime effect. Always pair with a null guard before relying on the narrowed type.Shown above the full answer for quick recall.Answer (EN)Image**`NonNullable<T>`** removes `null` and `undefined` from type `T`, leaving only the values that can actually be there. ## Theory ### TL;DR - Think coffee filter: you pour in a type with `null` and `undefined` mixed in, and get back only the real type. - Implementation: `T extends null | undefined ? never : T` - TypeScript distributes this over each union member. - Use after a null guard (`if (!user) return`), not instead of one. - It only strips top-level `null`/`undefined`. Nested nulls inside objects survive. - Semantically identical to `Exclude<T, null | undefined>`, but the name signals intent better. ### Quick example ```typescript type MaybeUser = { name: string } | null | undefined; type User = NonNullable<MaybeUser>; // { name: string } // Practical use: after a null check function greet(user: User) { console.log(user.name); // no optional chaining needed } ``` The type tells TypeScript: "by the time this value reaches this function, null is already handled." ### Key difference from Exclude `NonNullable<T>` and `Exclude<T, null | undefined>` produce the same result for standard unions. The difference is intent. `NonNullable` signals "I guarantee this is non-null" in a code review, while `Exclude` reads as a generic subtraction. Pick `NonNullable` when your goal is specifically removing nullability. ### When to use - After a runtime null guard: if you do `if (!data) return;`, the next function can accept `NonNullable<typeof data>`. - Optional interface properties: `NonNullable<User["email"]>` gives you `string` from `string | undefined`. - Array filtering with proper type narrowing (the Examples section shows this). - Post-validation in API handlers, after confirming a response exists. Avoid wrapping raw type definitions in `NonNullable`. If a prop can be null, say so with `| null`. Reserve `NonNullable` for the narrowed, post-check side. ### How the compiler handles this TypeScript evaluates `NonNullable<string | null | undefined>` by distributing the conditional type over each union member. `string extends null | undefined` is false, so it stays. `null extends null | undefined` is true, so it becomes `never`. And `never` drops out of unions automatically. The whole thing is erased before TypeScript emits any JavaScript. ### Common mistakes **Expecting deep null removal:** ```typescript type HasInnerNull = { prop: string | null }; type Result = NonNullable<HasInnerNull | null>; // Result: { prop: string | null } <- inner null survives! ``` Only the top-level `null` is stripped. For deep removal, write a recursive `DeepNonNullable` mapped type or use Zod for runtime validation. **Treating it as a runtime check:** ```typescript function bad(user: User | null) { const safe: NonNullable<typeof user> = user!; return safe.name; // compiles fine, crashes at runtime if user is null } ``` `NonNullable` is type-only. Always pair it with an actual guard before using the narrowed type. **Applying it when there is nothing to strip:** ```typescript type Pointless = NonNullable<string>; // still string ``` Not an error, but it adds noise. Only use it when the type actually includes `null` or `undefined`. ### Real-world usage - React Query: after `if (!data) return null;`, pass `NonNullable<typeof data>` to child components that expect a real value. - Express: once `req.user` is populated by auth middleware, use `NonNullable<Request["user"]>` in route handlers. - Next.js API routes: `req.body` typed as `ParsedBody | null` becomes `NonNullable<typeof req.body>` after the null check. - Optional interface properties: extract a clean `string` from `string | null | undefined` with a single type utility. ### Follow-up questions **Q:** Write the implementation of `NonNullable<T>`. **A:** `type NonNullable<T> = T extends null | undefined ? never : T;`. TypeScript's standard library also has a version using `T & {}`, which produces the same result in practice. **Q:** What is the difference between `NonNullable<T>` and `Exclude<T, null | undefined>`? **A:** For union types, they produce identical results. `NonNullable` is the better choice when the intent is specifically removing nullability, because the name makes that obvious. **Q:** Does `NonNullable` remove nulls from nested object properties? **A:** No. It only strips top-level `null` and `undefined` from the union. `NonNullable<{ val: string | null } | null>` gives `{ val: string | null }`. For deep cleaning, you need a recursive mapped type. **Q:** How does it work with branded types? **A:** Brands are preserved. `NonNullable<(string & { readonly _brand: "UserId" }) | null>` returns the branded type intact, because the brand does not extend `null | undefined`. ## Examples ### Extracting non-null from optional properties ```typescript interface User { id: string; name: string; email?: string; // string | undefined phone?: string | null; // string | null | undefined } type RequiredEmail = NonNullable<User["email"]>; // string type RequiredPhone = NonNullable<User["phone"]>; // string function sendConfirmation(email: RequiredEmail) { console.log(`Sending to ${email}`); // no null check needed here } ``` `User["email"]` resolves to `string | undefined`. After `NonNullable`, you get plain `string`. This is a common pattern when you need to pass an optional property to a function that expects a definite value. ### Array filtering with type narrowing ```typescript const users: (User | null | undefined)[] = [ { id: "1", name: "Alice", email: "alice@example.com" }, null, { id: "2", name: "Bob", email: "bob@example.com" }, undefined, ]; // filter(Boolean) removes null/undefined at runtime, // but TypeScript still infers (User | null | undefined)[] // A type predicate fixes that: const validUsers = users.filter( (u): u is NonNullable<typeof u> => u != null ); // validUsers: User[] validUsers.forEach(u => console.log(u.name)); // Alice, Bob ``` The predicate `u is NonNullable<typeof u>` is what narrows the type. Without it, TypeScript keeps the nullable union even after filtering. In real code, I reach for this pattern any time I need to clean an array from an API response that might contain sparse null entries.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.