TypeScriptUnions and narrowing
Union (A | B)
A type that can be one of several types.
Example
#TypeScript
function formatId(id: string | number): string {
if (typeof id === 'number') {
return `#${id.toString().padStart(4, '0')}`
}
return id.toUpperCase()
}
console.log(formatId(42))
console.log(formatId('cw-html'))Result
#0042 CW-HTML
Definition and usage
#A union joins types with a vertical bar: string | number means a value that is either a string or a number. It’s one of the most commonly used mechanisms in TypeScript, because data in real programs often comes in more than one shape.
On a value of a union type, you can immediately use only what is common to all its members. To use the methods of one specific type, you first need to narrow it, for example with a typeof check.
Literal unions ("easy" | "medium" | "hard") are a simple, lightweight way to list allowed values, often more convenient than an enum.
Syntax
#Syntax
type Name = TypeA | TypeB | TypeCMore examples
#TypeScript
function length(value: string | number) {
return value.length
}
// Error: Property 'length' does not exist on type 'string | number'.Good practices
#- When the members of a union are objects, give them a shared field with a literal value (e.g.
kind). That creates a discriminated union that’s easy to narrow. - An array of elements of different types is
(string | number)[], notstring | number[].
Related entries
#- enum vs unionenum creates a named set of constants that also exists at runtime as an object, while a literal union is just a type, lighter and with no JavaScript code at all.
- Type narrowingDetermining a more precise type for a value based on checks in your code.
- Discriminated unionsUnions of objects with a shared tag field that makes it easy to tell the variants apart.
- Intersection (A & B)A type that combines all the fields of several types at once.
- Literal typesTypes that allow only specific values, e.g. "easy" | "hard".
Spotted a mistake or missing an example? Write to us.