NonNullable type in Typescript - Time & Space Complexity
Let's explore how the NonNullable type affects the time it takes for TypeScript to process types.
We want to see how the work grows when removing null and undefined from types.
Analyze the time complexity of the following TypeScript type operation.
type NonNullable<T> = T extends null | undefined ? never : T;
// Example usage:
type CleanType = NonNullable<string | null | undefined>;
This code removes null and undefined from a type union.
Look at what happens when TypeScript checks each part of the union.
- Primary operation: Checking each union member against null or undefined.
- How many times: Once for each member in the union type.
As the number of union members grows, TypeScript checks each one separately.
| Input Size (n) | Approx. Operations |
|---|---|
| 3 | 3 checks |
| 10 | 10 checks |
| 100 | 100 checks |
Pattern observation: The work grows directly with the number of union members.
Time Complexity: O(n)
This means the time to process grows linearly with the number of types in the union.
[X] Wrong: "Removing null and undefined happens instantly no matter how many types there are."
[OK] Correct: Each type in the union must be checked, so more types mean more work.
Understanding how type operations scale helps you write efficient and clear TypeScript code, a skill valued in many coding tasks.
What if we used a nested union type inside NonNullable? How would that affect the time complexity?
Practice
What does the NonNullable type do in TypeScript?
Solution
Step 1: Understand the purpose of NonNullable
TheNonNullabletype removesnullandundefinedfrom a given type, ensuring the value is always defined.Step 2: Compare options with definition
Only Removesnullandundefinedfrom a type correctly describes this behavior; others describe different or incorrect behaviors.Final Answer:
Removesnullandundefinedfrom a type -> Option CQuick Check:
NonNullable removes null and undefined [OK]
- Thinking it adds null or undefined
- Confusing it with making types optional
- Assuming it converts types to strings
Which of the following is the correct syntax to use NonNullable on a type T?
Solution
Step 1: Recall TypeScript generic syntax
TypeScript uses angle brackets<>to apply generic types, likeNonNullable<T>.Step 2: Match options with correct syntax
NonNullable<T>uses the correct generic syntax. Options A, C, and D use incorrect brackets or parentheses.Final Answer:
NonNullable<T> -> Option DQuick Check:
Generic types use <> brackets [OK]
- Using parentheses instead of angle brackets
- Using square brackets or curly braces
- Confusing function call syntax with type syntax
What is the type of value after this code runs?
type MaybeString = string | null | undefined; const value: NonNullable<MaybeString> = "hello";
Solution
Step 1: Understand the original type
MaybeStringcan bestring,null, orundefined.Step 2: Apply NonNullable to remove null and undefined
UsingNonNullable<MaybeString>removesnullandundefined, leaving onlystring.Final Answer:
string -> Option AQuick Check:
NonNullable removes null and undefined, leaving string [OK]
- Thinking the type still includes null or undefined
- Confusing NonNullable with Partial or Required
- Assuming the type becomes never
Identify the error in this code snippet:
type User = { name: string | null };
type CleanUser = NonNullable<User>;Solution
Step 1: Understand what NonNullable does
NonNullable removesnullandundefinedfrom a type itself, not from nested properties.Step 2: Analyze the code
The code is syntactically correct.NonNullable<User>results in the same type asUsersinceUseris not a union includingnullorundefinedat the top level.Final Answer:
There is no error; code is correct -> Option AQuick Check:
Code compiles without errors [OK]
- Believing NonNullable cleans nested properties automatically
- Thinking the syntax for NonNullable is incorrect
- Thinking NonNullable cannot be applied to object types
Given this type, how can you create a new type NonNullUser where the email property cannot be null or undefined using NonNullable?
type User = {
id: number;
email: string | null | undefined;
};Solution
Step 1: Understand the goal
We want to keepidas is, but makeemailexcludenullandundefined.Step 2: Apply NonNullable to the email property only
UsingNonNullable<string | null | undefined>onemailremovesnullandundefined, leaving juststring.Step 3: Check other options
type NonNullUser = NonNullable<User> removes null/undefined from the wholeUsertype, which does not affect nested properties. type NonNullUser = { id: number; email: string } changes the type but does not use NonNullable. type NonNullUser = { id: number; email: string | null } still allowsnull.Final Answer:
type NonNullUser = { id: number; email: NonNullable<string | null | undefined> } -> Option BQuick Check:
Apply NonNullable only to the property needing it [OK]
- Applying NonNullable to the whole object type
- Not removing null and undefined from email
- Changing type without NonNullable
Ready to prove it?
Pass the test and this pattern moves unknown
