Introduction: Why "just if (value)" Can Let You Down?
Every developer transitioning from JavaScript to TypeScript will sooner or later face the question: "Is there a way to check for both null and undefined?". This question has garnered thousands of views on Stack Overflow — and for good reason. At first glance, the task seems trivial: write if (value != null) or if (value). But as always, the devil is in the details.
In this article, we'll break down the top mistakes that beginners (and not only) make when checking for null and undefined in TypeScript. You'll learn why loose comparison can be more dangerous than it seems, how the Nullish Coalescing (??) operator works, and when to use custom type guards. Let's go!
Mistake #1: Using if (!value) for All Falsy Values
The most common anti-pattern is trying to check for a value using negation:
// ❌ Badfunction processInput(input: string | null | undefined) { if (!input) { console.log('Input is missing'); return; } console.log(input.toUpperCase());}
processInput(''); // ❌ Will output "Input is missing", even though the string is empty, but NOT null and NOT undefinedThe problem is that !value converts any falsy value to true. In TypeScript (and JavaScript), falsy values include: false, 0, '' (empty string), NaN, null, undefined. If your business logic allows an empty string or the number 0, this code will break.
How to avoid: Use strict checking for null and undefined with === or !==.
Mistake #2: Blindly Trusting value == null
Many developers know that value == null (double equals) checks for both null and undefined at the same time. This does work:
// ✅ Works, but...function check(value: string | null | undefined) { if (value == null) { console.log('value is null or undefined'); }}However, double equals in TypeScript is a source of non-obvious bugs. For example, null == undefined is true, but null == false is false. And what about '' == false? Also true. Loose comparison can behave unpredictably, especially in complex conditions.
How to avoid: In TypeScript, value == null is an officially allowed pattern (linters often permit it), but for beginners it's better to stick with an explicit approach: value === null || value === undefined.
Mistake #3: Ignoring undefined When Working with Objects
Sometimes developers only check for null, forgetting about undefined:
// ❌ Dangerousinterface User { name?: string; age: number | null;}
function greet(user: User) { if (user.age !== null) { console.log(`Age: ${user.age}`); } // If age is not passed (undefined), the code will execute!}
greet({ name: 'Alice' }); // Will output "Age: undefined"The age field can be null, number, or undefined (if not specified in the interface). Checking only for null misses undefined.
How to avoid: Always check for both values if the type allows both. Or use the Optional Chaining (?.) operator and Nullish Coalescing (??).
The Best Way: Strict Checking with ===
The mos