Skip to main content

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.

In TypeScript, the ?: syntax is not a single operator or contiguous token, but rather the sequential pairing of the Optional Modifier (? or QuestionToken) and the Type Annotation Separator (: or ColonToken). This sequence is primarily used in structural declarations to mark a member as optional while simultaneously defining its type. In expression and type-level contexts, the ? and : tokens operate independently as components of conditional logic. Optional Modifier and Type Annotation In property, parameter, and tuple declarations, the ? token marks the preceding entity as optional. The : token following it introduces the type annotation. Because they are distinct tokens in the Abstract Syntax Tree (AST), they can legally be separated by whitespace. The placement of the ? token depends strictly on the declaration context:
  • Immediately after an identifier (in classes, interfaces, parameters, and labeled tuples).
  • Immediately after the closing bracket of an index signature (in mapped types).
  • Immediately after the type itself (in unlabeled tuple elements).
While the : and subsequent type annotation can be omitted in class properties, interface properties, and function parameters (defaulting to any), they are strictly required in mapped types and labeled tuple elements. Omitting the : in these contexts results in a syntax error. Mechanically, the TypeScript compiler implicitly unions the explicitly declared type with undefined. If the exactOptionalPropertyTypes compiler option is enabled, the property must either be omitted entirely or set to the exact declared type, rejecting explicit undefined assignments unless | undefined is manually appended to the type definition.
// Classes and Interfaces (Identifier followed by ? and optional :)
interface Entity {
  id? : string;     // Whitespace is legal between ? and :
  untypedProperty?; // : and type annotation are optional here (resolves to any | undefined)
}

// Mapped Types (Placed after the index signature closing bracket; : is strictly required)
type OptionalMapped<T> = {
  [K in keyof T]?: T[K];
};

// Function Parameters (Must appear after all required parameters)
function execute(param?: number): void {}

// Labeled Tuple Elements (Identifier followed by ?; : is strictly required)
type Coordinate = [x: number, y: number, z?: number];

// Unlabeled Tuple Elements (Placed immediately after the type itself)
type StringNumberTuple = [string, number?];
Conditional Contexts When the ? and : tokens appear in expression contexts rather than declaration contexts, they function as delimiters for conditional branching. Conditional Types (Type System) At the type level, ? and : form a conditional type. This construct selects one of two possible types based on an assignability relationship evaluated using the extends keyword. The ? precedes the true branch, and the : precedes the false branch.
// Syntax Template
type TrueType = { isTrue: true };
type FalseType = { isTrue: false };
type ConditionalType<T, U> = T extends U ? TrueType : FalseType;

// Type Inference Example
type IsString<T> = T extends string ? true : false;
type A = IsString<"hello">; // Resolves to: true
Conditional (Ternary) Operator (Runtime Logic) At runtime, ? and : form the ternary operator, evaluating an expression-based if...else statement. The TypeScript type checker infers the return type of the entire expression as a union of the true and false operands’ types, subject to standard type widening rules based on the assignment target.
declare const condition: boolean;

// Inferred as literal union: "stringVal" | 42
const result = condition ? "stringVal" : 42; 

// Widened to: string | number
let mutableResult = condition ? "stringVal" : 42;
Master TypeScript with Deep Grasping Methodology!Learn More