Learning outcomes
- Enforce strict null safety across APIs
- Write custom type predicates and assertion functions
Mental model
In strict mode (strictNullChecks: true), null and undefined are distinct domain types, eliminating Tony Hoare's "billion-dollar mistake" of unhandled null pointer dereferences.
Theory
TypeScript's control flow engine tracks variable assignments, truthiness checks, equality guards, and custom type predicates (value is User). Custom assertion functions (asserts condition) narrow types in the calling scope by throwing an error if the condition evaluates to false.
export interface UserProfile {
id: string;
email: string;
avatarUrl?: string | null;
}
export function isDefined<T>(val: T | null | undefined): val is T {
return val !== null && val !== undefined;
}
export function assertNonNull<T>(val: T | null | undefined, msg: string): asserts val is T {
if (val === null || val === undefined) {
throw new Error(`[Assertion Error]: ${msg}`);
}
}
export function processUserAvatar(user: UserProfile): string {
const avatar = user.avatarUrl?.trim() ?? "https://cdn.example.com/default-avatar.png";
assertNonNull(user.email, "User must have a valid email address");
return `${user.email}:${avatar}`;
}
Alternatives and trade-offs
- Non-null assertion operator (
!): Tells TypeScriptvalue!is non-null without checking. Risky; throws runtimeTypeErrorif wrong. - Explicit Type Guards (
isDefined): Type-safe runtime check that narrows types automatically.
Failure modes and misconceptions
||vs??Operator: The logical OR operator (||) falls back on falsy values ("",0,false). Nullish coalescing (??) falls back ONLY onnullorundefined.- Abusing
!assertion: Usinguser!.emailbypasses type checking without runtime protection.
Decision scenario
Use nullish coalescing (??) when providing fallbacks for missing API string or numeric fields. Avoid the non-null assertion operator (!) in production application code.
Learning outcomes
- Configure
strictNullChecksto eliminate unhandled null pointer bugs. - Implement custom type predicates (
val is T) for collection filtering. - Author scope-narrowing assertion functions (
asserts val is T).
Trade-offs
Strict null checking prevents runtime null reference exceptions, but requires explicit guards or default fallbacks whenever handling optional network data.
Evidence assessment
Theory and decision mastery
Decision scenario
A team is building an API client where network responses contain optional fields (avatarUrl).
Which pattern safely provides a default avatar URL when avatarUrl is missing or null?
Primary sources
- TypeScript 5.4 Language Specification & Type System Mechanics — Microsoft, verified 2026-07-22