Question
In TypeScript, what is the correct way to check whether a value is either null or undefined?
Because TypeScript is strongly typed, using a loose conditional such as if (value) {} does not seem precise enough when the goal is specifically to detect null and undefined.
Is there a dedicated TypeScript feature, built-in function, or syntax shortcut for checking both cases safely and clearly?
Short Answer
By the end of this page, you will understand how to check for null and undefined in TypeScript, when to use value == null, when to use strict comparisons, and why if (value) is often the wrong tool for this job. You will also see how these checks affect type narrowing in real code.
Concept
In TypeScript, null and undefined are two distinct values.
undefinedusually means a value was not provided or has not been assigned.nullusually means a value was intentionally set to “no value”.
Even though they are different, developers often need to treat them the same way: “this value is missing”.
That is why checks for both null and undefined are very common.
Why if (value) is not enough
A truthy check like this:
if (value) {
// ...
}
does not only exclude null and undefined. It also excludes other falsy values such as:
0""falseNaN
So if 0 or an empty string are valid values in your program, if (value) can give the wrong result.
Common ways to check
1. Check both explicitly
if (value !== null && value !== undefined) {
// value is present
}
This is the most explicit and beginner-friendly approach.
2. Use value == null
if (value == null) {
// value is either null or undefined
}
This is one of the few places where loose equality is commonly and intentionally used in JavaScript and TypeScript.
value == nullmeansvalueisnullorundefinedvalue != nullmeansvalueis neithernullnorundefined
This works because JavaScript defines null == undefined as true, while other values do not match.
Why this matters in TypeScript
TypeScript uses these checks for type narrowing. That means after a successful null/undefined check, TypeScript can often treat the value as a non-null type.
Example:
function printLength(text: string | null | undefined) {
if (text != null) {
console.log(text.length);
}
}
Inside the if block, TypeScript knows text is a string.
This makes your code safer and reduces runtime errors such as:
Cannot read properties of null
Mental Model
Think of a variable as a mailbox.
undefinedmeans the mailbox was never given a letter.nullmeans someone deliberately placed a note saying, “there is no letter.”
In both cases, you still do not have a real message to read.
A check like value == null is like asking:
“Is the mailbox effectively empty, whether nothing was ever delivered or it was explicitly marked empty?”
A truthy check like if (value) asks a different question:
“Does this value look usable in a general boolean sense?”
That second question is broader, so it may reject values that are perfectly valid, such as 0 or "".
Syntax and Examples
Core syntax
Check for both null and undefined
if (value == null) {
// value is null or undefined
}
if (value != null) {
// value is neither null nor undefined
}
Explicit strict comparison
if (value === null || value === undefined) {
// missing value
}
if (value !== null && value !== undefined) {
// present value
}
Example 1: Safe string handling
function greet(name: string | null | undefined) {
if (name == null) {
console.log("Hello, guest!");
return;
}
console.log(`Hello, ${name}!`);
}
Here, name == null covers both missing cases.
Example 2: Why truthy checks can fail
function printCount(count: number | null | undefined) {
if (count) {
console.log(`Count is ${count}`);
} else {
console.log("Count is missing");
}
}
printCount(0);
This prints the wrong result because 0 is falsy.
A better version is:
function printCount(count: number | null | undefined) {
if (count != null) {
console.log(`Count is ${count}`);
} else {
console.log("Count is missing");
}
}
Now 0 is handled correctly.
Example 3: Optional values from APIs
type User = {
email?: string | null;
};
function showEmail(user: User) {
if (user.email != null) {
console.log(user.email.toLowerCase());
} else {
console.log("No email available");
}
}
This is common when API fields may be absent or explicitly null.
Step by Step Execution
Consider this example:
function printMessage(message: string | null | undefined) {
if (message != null) {
console.log(message.toUpperCase());
} else {
console.log("No message");
}
}
printMessage("hello");
printMessage(null);
printMessage(undefined);
Step by step
Call 1: printMessage("hello")
messagereceives the string"hello"- The condition
message != nullis checked "hello"is neithernullnorundefined- The condition is
true - TypeScript narrows
messagetostringinside the block message.toUpperCase()runs and printsHELLO
Call 2: printMessage(null)
messagereceivesnull- The condition
message != nullis checked - Since
messageisnull, the condition isfalse - The
elseblock runs - It prints
No message
Call 3: printMessage(undefined)
messagereceivesundefined- The condition
message != nullis checked - Since
messageisundefined, the condition isfalse - The
elseblock runs - It prints
No message
Key result
The single check message != null safely handles both missing-value cases while still allowing valid values like empty strings.
Real World Use Cases
Where this is used
Form input handling
A field may be missing, intentionally blank, or contain a real value.
function validateAge(age: number | null | undefined) {
if (age == null) {
return "Age is required";
}
return age >= 18 ? "Adult" : "Minor";
}
API responses
External APIs often return optional or nullable properties.
type Product = {
price?: number | null;
};
function formatPrice(product: Product) {
if (product.price == null) {
return "Price unavailable";
}
return `$${product.price.toFixed(2)}`;
}
Configuration values
Apps often read environment values that may be absent.
function getPort(port: number | undefined) {
return port != null ? port : 3000;
}
Database fields
A database column may allow NULL, while missing application data may show up as undefined.
function canSendReminder(lastLogin: Date | null | undefined) {
if (lastLogin == null) {
return false;
}
return true;
}
Real Codebase Usage
In real projects, developers usually combine null/undefined checks with a few common patterns.
Guard clauses
A guard clause exits early when required data is missing.
function sendEmail(address: string | null | undefined) {
if (address == null) {
throw new Error("Email address is required");
}
console.log(`Sending email to ${address}`);
}
This keeps the rest of the function simpler.
Default values
If a value is missing, provide a fallback.
function getDisplayName(name: string | null | undefined) {
return name ?? "Anonymous";
}
The ?? operator only falls back for null and undefined, not for "" or 0.
Validation before processing
function saveScore(score: number | null | undefined) {
if (score == null) {
return { success: false, error: "Score is missing" };
}
return { success: true, value: score };
}
Optional chaining with null checks
type Profile = {
contact?: {
email?: string | null;
};
};
function getEmail(profile: Profile) {
return profile.contact?.email ?? "No email";
}
Filtering out nullish values
This is common when cleaning data.
const values: Array<number | null | undefined> = [1, null, 2, undefined, 3];
const presentValues = values.filter((value) => value != null);
In many codebases, this style is preferred because it is short, readable, and expresses exactly what “present” means.
Common Mistakes
1. Using if (value) when 0, false, or "" are valid
Broken example:
function showPrice(price: number | null | undefined) {
if (price) {
console.log(price);
} else {
console.log("Missing price");
}
}
If price is 0, this incorrectly says it is missing.
Use this instead:
if (price != null) {
console.log(price);
}
2. Forgetting that null and undefined are different values
Broken example:
if (value === null) {
// only catches null, not undefined
}
If you need both, use:
if (value == null) {
// catches both
}
3. Avoiding == null because all loose equality seems bad
Usually, == is discouraged. But value == null is a well-known exception because it intentionally matches exactly two values:
nullundefined
It does not match 0, false, or "".
4. Using || instead of ?? for defaults
Broken example:
const count = input || 10;
If input is 0, this wrongly becomes 10.
Use:
const count = input ?? 10;
5. Assuming TypeScript always narrows after unclear checks
TypeScript narrows best when your condition clearly expresses nullish checking.
Good:
if (value != null) {
value.toString();
}
Less precise for intent:
if (value) {
value.toString();
}
The second check mixes nullish checking with truthiness.
Comparisons
| Approach | Checks for null | Checks for undefined | Rejects 0/""/false | Best use |
|---|---|---|---|---|
if (value) | Yes indirectly | Yes indirectly | Yes | General truthy/falsy logic |
value == null | Yes | Yes | No | Check for missing value |
value != null | Excludes null | Excludes undefined | No | Check that value is present |
value === null | Yes | No | No | Only when null specifically matters |
value === undefined | No | Yes | No | Only when undefined specifically matters |
value !== null && value !== undefined | Excludes null | Excludes undefined | No | Most explicit form |
value ?? fallback | Handles null | Handles undefined | No | Set default values |
| `value | fallback` | Handles many falsy values | Handles many falsy values |
Rule of thumb
- Use
value == nullwhen you want to know if a value is missing. - Use
value != nullwhen you want to know if a value is present. - Use
??when you want a default only fornullorundefined. - Avoid
if (value)if0,false, or""should be allowed.
Cheat Sheet
Quick reference
Check for missing value
value == null
True when value is:
nullundefined
Check for present value
value != null
True when value is not:
nullundefined
Explicit strict version
value === null || value === undefined
value !== null && value !== undefined
Use a default only for nullish values
const result = value ?? fallback;
Avoid this when valid values can be falsy
if (value) {
// may reject 0, false, ""
}
Best practices
- Prefer
value != nullfor a short present-value check. - Prefer strict comparisons when you want maximum explicitness.
- Use
??instead of||for null/undefined defaults. - Let TypeScript narrow types after nullish checks.
Edge case reminder
null == undefined // true
null === undefined // false
FAQ
Is value == null valid in TypeScript?
Yes. It is a common and intentional way to check whether a value is either null or undefined.
Should I use if (value) to check for null and undefined?
Usually no. It also treats 0, false, "", and NaN as false, which may not match your intent.
What is the difference between null and undefined in TypeScript?
undefined usually means a value was not assigned or provided. null usually means the absence of a value was intentional.
Is == null better than === null || === undefined?
They are both correct. == null is shorter, while the strict version is more explicit.
Does TypeScript narrow types after value != null?
Yes. In many cases, TypeScript understands that the value is no longer null or undefined inside that branch.
Should I use || or ?? for fallback values?
Use ?? if you only want to replace null or undefined. Use || only when you want all falsy values to trigger the fallback.
Is there a built-in TypeScript function for null and undefined checks?
There is no special dedicated built-in function for this. Developers typically use value == null, value != null, strict comparisons, or ??.
Mini Project
Description
Build a small TypeScript utility for displaying profile information where some fields may be missing. This project demonstrates how to correctly check for null and undefined without accidentally rejecting valid values like 0 or an empty string.
Goal
Create a function that safely formats user profile data and provides sensible fallbacks only when values are actually missing.
Requirements
- Define a
UserProfiletype with nullable or optional fields. - Create a function that prints a user's name, age, and bio.
- Treat
nullandundefinedas missing values. - Do not treat
0as missing for age. - Use
??or!= nullwhere appropriate.
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Accessing Input Value from EventTarget in TypeScript
Learn why EventTarget has no value property in TypeScript and safely read values from HTML input events in Angular applications.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.