TypeScript Null Safety
A quick reference for handling null and undefined with optional chaining, coalescing, and strict guards.
TL;DR
- Navigate nested properties safely using optional chaining
?.operators. - Provide fallback defaults for nullish values with double question
??marks. - Eliminate
nullandundefinedusing strict equality guard checks.
Optional Chaining
property chainingShort-circuits to undefined if target object is nullish.
type User = { profile?: { name: string } };
function getName(u?: User) {
return u?.profile?.name;
}method chainingInvokes optional methods only if they exist on the object.
type Worker = { stop?: () => void };
function halt(w?: Worker) {
w?.stop?.();
}element indexingSafely accesses array elements or dynamic dictionary keys.
function getFirstTag(tags?: string[]) {
return tags?.[0];
}Nullish Coalescing
?? operatorSupplies fallback defaults only for null or undefined.
const input: string | null = null;
const text = input ?? 'Default text';preserving zeroRetains numeric zeros without triggering fallback defaults.
function setLimit(max?: number) {
return max ?? 50; // preserves 0
}chained defaultsCascades multiple fallback lookups in order of priority.
const host = envHost ?? configHost ?? 'localhost';Type Guards for Null
strict equality guardNarrows nullable types by checking inequality with null.
function printLength(str: string | null) {
if (str !== null) {
console.log(str.length);
}
}truthiness narrowingDiscards nullish states along with other falsy values.
function display(val?: string) {
if (val) {
console.log(val.toUpperCase());
}
}NonNullable helperStrips null and undefined from an existing union type.
type Raw = string | number | null | undefined;
type Clean = NonNullable<Raw>; // string | numberOptional vs Nullable
optional propertyAllows omitting property from object structure entirely.
interface Config {
port?: number; // number | undefined
}explicit null unionRequires key presence while permitting an intentional null value.
interface Record {
id: string;
deletedAt: Date | null;
}exactOptionalPropertyTypesDistinguishes omitted keys from keys assigned undefined.
interface Props {
color?: string;
}
// Under exactOptional, { color: undefined } is invalidNon-Null Assertion
! assertion operatorForces compiler to treat a nullable expression as non-null.
const el = document.getElementById('app')!;
el.textContent = 'Hello World';definite assignmentInforms compiler that property is initialized out-of-line.
class Server {
address!: string;
init() { this.address = '0.0.0.0'; }
}runtime guard alternativeReplaces dangerous assertions with explicit error checks.
function requireValue<T>(val: T | null): T {
if (val === null) throw new Error('Null value');
return val;
}Tips
- Always enable
strictNullChecksin yourtsconfig.jsonto prevent silent null dereferencing errors across your entire codebase. - Prefer the nullish coalescing
??operator over logical OR||when zero or empty strings represent valid input values.
Warnings
- Avoid the non-null assertion
!operator because it suppresses compiler warnings without providing any runtime validation. - Remember that
Array.find()returns undefined when no match exists, requiring explicit nullish checks before property access.
In Practice
Demonstrates optional chaining, nullish coalescing, and strict narrowing when extracting nested config preferences.
- Define an interface structure with optional nested theme configurations.
- Use optional chaining to inspect deeply nested color properties safely.
- Supply sensible fallback values with nullish coalescing operators.
- Narrow and return clean presentation objects with guaranteed presence.
interface Theme {
colors?: { primary?: string };
size?: number;
}
interface Config {
theme?: Theme | null;
}
function resolveConfig(cfg?: Config) {
const color = cfg?.theme?.colors?.primary ?? '#06c';
const size = cfg?.theme?.size ?? 14;
return { color, size };
}
const prefs: Config = { theme: { size: 16 } };
const active = resolveConfig(prefs);
console.log(`Theme size: ${active.size}`);FAQ
Optional chaining (?.) short-circuits to undefined exclusively when encountering null or undefined. The logical AND operator (&&) evaluates truthiness, short-circuiting on valid falsy values such as 0, false, or empty strings.
The nullish coalescing operator (??) only triggers fallback evaluation when the left operand is strictly null or undefined. In contrast, the logical OR operator (||) replaces all falsy values, which inadvertently overwrites legitimate numeric zeros or boolean falses.
const count = 0;
const a = count || 10; // 10 (overwritten!)
const b = count ?? 10; // 0 (preserved)The postfix exclamation mark (!) tells the compiler to treat a value as non-null without performing any runtime validation. If the value actually turns out to be null or undefined during execution, your code will crash with an unhandled TypeError.
When strictNullChecks is enabled, null and undefined become distinct types rather than universal subtypes of every type. As a result, you cannot assign null to a string variable without explicitly declaring a union like string | null.