Union Type Syntax
Union types are created using the pipe symbol (|) between types. This allows variables to hold values of any of the specified types, providing flexibility while maintaining type safety.
About 863 wordsAbout 11 min
2025-08-05
Note
Union types allow TypeScript to model values that can be one of several types. This powerful feature enables flexible APIs while maintaining type safety, making it possible to create functions that accept multiple input types in a type-safe manner.
Union types provide a way to express that a value can be one of several types, using the pipe symbol (|) to combine types.
Union Type Syntax
Union types are created using the pipe symbol (|) between types. This allows variables to hold values of any of the specified types, providing flexibility while maintaining type safety.
Type Guards
Type guards are TypeScript's way of narrowing down the type within a conditional block. Using typeof, instanceof, or custom type predicates helps the compiler understand the specific type being used.
Type Narrowing
TypeScript automatically narrows types in conditional blocks. When you check for a specific type using a type guard, the compiler knows the variable has that type within that block.
Union types enable flexible function signatures while maintaining type safety through proper type checking.
Basic Union Types
Union types allow variables to accept multiple types, making APIs more flexible while maintaining type safety.
function display(value: string | number) {
console.log(value);
}
display("Hello"); // Valid
display(42); // Valid
display(true); // Error: Argument of type 'boolean' is not assignableStep 1
Type Guards for Disambiguation
Use typeof to check primitive types within union types. TypeScript automatically narrows the type in conditional blocks.
function formatValue(value: string | number): string {
if (typeof value === "string") {
return value.toUpperCase(); // TypeScript knows value is string
} else {
return value.toFixed(2); // TypeScript knows value is number
}
}Step 2
Complex Union Types
Union types can include functions, objects, and other complex types, enabling sophisticated APIs.
type ValueProvider = string | number | (() => string);
function getValue(provider: ValueProvider): string {
if (typeof provider === "function") {
return provider(); // Call the function
} else if (typeof provider === "string") {
return provider; // Return the string
} else {
return provider.toString(); // Convert number to string
}
}Step 3
Union types shine in real-world scenarios where APIs need to handle multiple input types gracefully.
CSS Property Values Union types are perfect for modeling CSS properties that accept different value types.
type CSSValue = string | number;
function setStyle(element: HTMLElement, property: string, value: CSSValue) {
if (typeof value === "number") {
element.style.setProperty(property, `${value}px`);
} else {
element.style.setProperty(property, value);
}
}
// Usage examples
setStyle(document.body, "width", 100); // Adds 'px' automatically
setStyle(document.body, "color", "red"); // Uses string directlyAPI Response Handling Union types can model different response formats from APIs.
type APIResponse =
| { success: true; data: User[] }
| { success: false; error: string };
function handleResponse(response: APIResponse) {
if (response.success) {
console.log(`Found ${response.data.length} users`);
} else {
console.error(`Error: ${response.error}`);
}
}Configuration Objects Flexible configuration options can be modeled with union types.
type LogLevel = "debug" | "info" | "warn" | "error";
type LogDestination = "console" | "file" | "remote";
interface LoggerConfig {
level: LogLevel;
destination: LogDestination;
format?: "json" | "text";
}When working with complex union types, proper disambiguation ensures type safety and enables TypeScript's type inference.
typeof Operatorstring
primitive
Use typeof to distinguish between primitive types (string, number, boolean, function, object). This is the most common type guard for union types.
instanceof Operatorstring
objects
Use instanceof to check if an object is an instance of a particular class. This helps distinguish between different object types in a union.
Custom Type Predicatesstring
custom
Create custom type guard functions that return a type predicate. These are useful for complex type checking logic that you want to reuse.
Discriminated Unionsstring
structured
Use discriminated unions where each type in the union has a common property (discriminant) that TypeScript can use to distinguish between types.
A practical example showing how union types can model complex data structures like JSON values:
type JsonValue =
| string
| number
| boolean
| null
| JsonValue[]
| { [key: string]: JsonValue };
function jsonToString(json: JsonValue): string {
if (json === null) return 'null';
switch (typeof json) {
case 'string':
case 'boolean':
case 'number':
return String(json);
}
if (Array.isArray(json)) {
return `[${json.map(jsonToString).join(', ')}]`;
}
// Handle object case
const entries = Object.entries(json)
.map(([key, value]) => `"${key}": ${jsonToString(value)}`);
return `{${entries.join(', ')}}`;
}A TypeScript construct that allows a variable to hold values of multiple specified types, separated by the | symbol, providing flexibility while maintaining type safety.
A TypeScript expression that performs a runtime check to determine the type of a value, allowing the compiler to narrow the type within conditional blocks.
The process by which TypeScript reduces the possible types of a variable within a specific code block based on type checks or control flow analysis.
A pattern where each type in a union has a common property (discriminant) that TypeScript can use to distinguish between the different types automatically.
c50b0-feat: some nots for tson Copyright Ownership:WARREN Y.F. LONG
License under:Attribution-NonCommercial-NoDerivatives 4.0 International (CC-BY-NC-ND-4.0)