null, undefined and void
"Cannot read properties of undefined" is probably the most common JavaScript crash of all time. TypeScript's strict null checks exist to stop it: they make "this might be missing" part of the type, so you cannot forget it.
The rule
Missing must be spelled out; void means nothing comes back.
JavaScript has two "nothing" values:
undefined— what you get when something was never set: a missing property, a variable with no value, a function that returns nothing.null— an empty value someone set on purpose: "there is deliberately no due date".
Each has a type of the same name. With strictNullChecks (part of strict), neither fits into other types unless you say so, using a union with |:
let due: string = null; // error
let due2: string | null = null; // fine
function findTask(id: number): Task | undefined {
return tasks.find(t => t.id === id);
}
const task = findTask(3);
task.title; // error: task may be undefined
if (task) {
task.title; // fine: inside the check, task is a Task
}Optional properties use ?, which adds undefined to the type for you: due?: string means the property may be missing, and reading it gives string | undefined.
void is different. It is the return type of a function that does not give back a useful value:
function logTask(task: Task): void {
console.log(task.title);
}Such a function actually returns undefined at runtime, but void says something stronger about intent: callers should not use the result.
The shortcut
Ask one question for each value: "Can this be absent?"
- Yes → add
| undefined(or| null, or use?for a property), and check before use. - It is a function's result that nobody should use →
void. - No → leave the plain type, and TypeScript guarantees it is present.
Can it be absent?
findTask(99)finds nothing when there is no task 99. Yes, so returnTask | undefined.
The trap is turning strictNullChecks off to make errors go away. Every error it reports is a place where the code could crash with "undefined".
Drills
Answer fast — trust the rule.
Under strict null checks, let due: string = null; is an error. What is the right fix?
What is the type of task.due when the property is declared due?: string?
Which return type fits a function that only writes to the console?
findTask returns Task | undefined. What must happen before reading .title?
Remember
- Missing must be spelled out; void means nothing comes back.
- Ask "can this be absent?": yes means a union with undefined or null, then a check.
- Trap: turning off strictNullChecks hides real crashes instead of fixing them.
