The Billion-Dollar Mistake: Handling `null`
The Most Common JavaScript Error
What is the most common error in JavaScript? It's probably this one:
TypeError: Cannot read properties of null (reading '...')
TypeError: Cannot read properties of undefined (reading '...')
This error, which computer scientist Tony Hoare called his "billion-dollar mistake," happens when you try to use a variable that you thought was an object, but it was actually null
or undefined
.
In JavaScript, this is a runtime error. Your app crashes, your users are unhappy. In TypeScript, this is a compile-time error, thanks to a setting called strictNullChecks
.
The strictNullChecks
Safety Net
In our live editor (and in any modern TypeScript project), the strictNullChecks
setting is enabled. This means TypeScript is intensely aware of null
and undefined
. It treats them as distinct types that you must explicitly handle.
Let's see what happens when a function might return a value or null
.
Exercise 1: The "Object is possibly 'null'" Error
- We have a function
findUserById
that returns aUser
object ornull
. - The code below calls the function and immediately tries to access
foundUser.name
. - Hover over the error on
foundUser
. TypeScript is stopping you, warning you thatfoundUser
could benull
, and you can't get the.name
ofnull
.
TypeScript just saved you from a potential runtime crash. But how do we fix it?
How to Fix "Object is possibly 'null'" Errors
The fix is simple and promotes safe coding habits: you must check if the value is "truthy" before you try to use it. The most common way is with an if
statement.
Exercise 2: Narrowing the Type
- Take the code from the previous exercise.
- Wrap the
console.log
line in anif (foundUser)
block. - Notice the error disappears inside the block.
Click to see the solution
type User = { name: string };
const users: User[] = [{ name: "Luigi" }, { name: "Mario" }];
function findUserById(id: number): User | null {
return users[id] ?? null;
}
const foundUser = findUserById(1);
// ✅ Correct!
if (foundUser) {
// Inside this block, TypeScript knows foundUser is a User, not null.
console.log(foundUser.name);
} else {
console.log("User not found.");
}
This is called type narrowing. Outside the if
block, the type of foundUser
is User | null
. But inside the if
block, TypeScript is smart enough to narrow that type down to just User
, because the check has proven it can't be null
.
By forcing you to explicitly handle the null
case, TypeScript turns a potential bug into a robust, well-handled piece of code.