Documentation Index
Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
Use this file to discover all available pages before exploring further.
The ?. (optional chaining) operator evaluates an object property, array element, or function call, immediately short-circuiting and returning undefined if the left-hand side (LHS) operand evaluates to a nullish value (null or undefined). It strictly checks for nullish values, meaning it will continue evaluation for other falsy values such as 0, "", NaN, or false.
Type-Level Implications
At the type level, the TypeScript compiler automatically unions undefined to the evaluated expression’s return type. If a property prop is defined as type T, the optional chaining expression obj?.prop will resolve to type T | undefined. This type mutation ensures strict type safety by forcing subsequent operations to account for the potential undefined result yielded by a short-circuited chain.
Syntax Variants
The operator supports three distinct syntactic forms depending on the operation being performed: ?.identifier, ?.[expression], and ?.(args).
interface Target {
staticProp: string;
method?: (arg: string) => void;
}
const target: Target | null = null;
const array: string[] | null = null;
const func: (() => void) | null = null;
const key = "staticProp";
// 1. Static Property Access (?.identifier)
const v1 = target?.staticProp;
// 2. Dynamic Property / Element Access (?.[expression])
// The ?. operator immediately precedes the bracket notation.
const v2 = target?.[key];
const v3 = array?.[0];
// 3. Function / Method Invocation (?.(args))
// The ?. operator immediately precedes the parentheses.
const v4 = func?.();
const v5 = target?.method?.("argument");
Evaluation Mechanics
When the TypeScript compiler processes the ?. operator, it injects a ternary-like nullish check.
const obj: { prop: string } | null = null;
// TypeScript Source
const value = obj?.prop;
// Logical Equivalence (Pre-ES2020 Transpilation)
const equivalentValue = (obj === null || obj === undefined) ? undefined : obj.prop;
Short-Circuiting Behavior
If the LHS operand is nullish, evaluation of the optional chain halts immediately. Short-circuiting applies strictly to the remainder of the optional chain itself, not to operations outside of it. Any subsequent property accesses, function calls, or side effects within the chain are bypassed, but adjacent expressions in the broader statement will still execute.
let x = 0;
let y = 0;
const a: { b?: (val: number) => string } | null = null;
// Because 'a' is nullish, the optional chain 'a?.b?.(++x)' short-circuits.
// 1. 'b' is never accessed.
// 2. The function is never invoked.
// 3. The increment operation (++x) inside the chain is bypassed.
// HOWEVER, operations outside the optional chain, like (++y), still execute.
const result = [a?.b?.(++x), ++y];
// State after execution:
// x === 0
// y === 1
// result === [undefined, 1]
When chaining multiple ?. operators, the first nullish evaluation short-circuits the entire chain:
const nestedObj: { prop1?: { prop2: string } } | null = null;
// If 'nestedObj' is nullish, it returns undefined immediately.
// It does not attempt to evaluate '.prop1' or '.prop2'.
const deepValue = nestedObj?.prop1?.prop2;
Syntactic Limitations
The optional chaining operator is strictly an accessor and evaluator. It triggers syntax errors when used in the following contexts:
const targetObj: { prop?: string } = {};
const ConstructorRef = class {};
const tagFunc = (strings: TemplateStringsArray) => strings[0];
// INVALID: Cannot be used on the left-hand side of an assignment
targetObj?.prop = "value";
// INVALID: Cannot be used with the 'new' keyword for instantiation
const instance = new ConstructorRef?.();
// INVALID: Cannot be used as a tagged template literal
const str = tagFunc?.`template`;
class Child extends class { method() {} } {
callSuper() {
// INVALID: Cannot be used to access properties on 'super'
super?.method();
}
}
Master TypeScript with Deep Grasping Methodology!Learn More