Taming TypeScript

The TypeScript Tutorial for The Hater

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

  1. We have a function findUserById that returns a User object or null.
  2. The code below calls the function and immediately tries to access foundUser.name.
  3. Hover over the error on foundUser. TypeScript is stopping you, warning you that foundUser could be null, and you can't get the .name of null.
Interactive Editor
Loading...

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

  1. Take the code from the previous exercise.
  2. Wrap the console.log line in an if (foundUser) block.
  3. Notice the error disappears inside the block.
Interactive Editor
Loading...
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.