Types and inference
Handle null and undefined deliberately
Include absent values in a type and check them before using the value under strict null checking.
Missing values cause a large share of JavaScript crashes: Cannot read properties of undefined. TypeScript’s answer is to make absence part of the type. A value that may be missing should say so:
function uppercase(value: string | undefined) {
return value === undefined ? '' : value.toUpperCase()
}
The explicit check narrows value to string in the second branch. Skip the check and call value.toUpperCase() directly, and under strict null checking the compiler stops you:
'value' is possibly 'undefined'.
That error is the whole feature. The crash that would have happened at runtime, on some unlucky input, is now a compile-time message pointing at the exact expression.
Two kinds of absence
JavaScript has both null and undefined, and TypeScript keeps them distinct. Use them according to the real boundary. Missing object properties and functions without a return commonly produce undefined. An API might use null deliberately — JSON has null but no undefined, so parsed responses carry null. Match your types to what the data actually contains.
Do not silence the check
Do not hide absence with a non-null assertion:
value!.toUpperCase()
The ! adds no runtime check. It only tells the compiler “trust me, this is not missing”. If the value is missing, JavaScript still fails — with the exact crash strict null checking exists to prevent. Every ! in a codebase is a place where the type system was overruled by hope.
Defaults with ??
Sometimes a default is the right behavior:
const label = value ?? 'Unknown'
The nullish coalescing operator uses the default only for null or undefined, not for valid empty strings. That distinction matters: value || 'Unknown' would also replace '', 0, and false, which are often legitimate values. Reach for ?? when only genuine absence should trigger the fallback.
After either an explicit check or ??, TypeScript narrows the type, and the rest of the code works with a plain string.
Exercise: write a function accepting number | null. Preserve 0 as valid input while returning a default only for null.
Lesson completed