Many JavaScript libraries support taking in values of more than one type. For example, jQuery’s `height`

and `width`

properties take an integer representing the number of pixels, or an integer along with an optional unit of measure appended (as a string).

Without union types, TypeScript definition files must represent this property as type `any`

, effectively losing type safety. This shortcoming could be worked around in function overloads as TypeScript supports function overloads (multiple functions with same name but different argument types). However, there is no equivalent for object properties, type constraints, or other type positions.

Union types let you represent a value which is one of multiple types. You can specify the types using the new `|`

operator.

function process(n: string|number) { /* ... */ } process('foo'); // OK process(42); // OK process($('div')); // Error

In the function body of `process`

, you can examine the type of an expression using `typeof`

or `instanceof`

operator. TypeScript understands these conditions and change type inference accordingly.

function process(n: string|number) { if (typeof n === 'number') { // Error because n is a number. console.log(n.toLowerCase()); } }

So far, Union types look a lot like a sum type in algebraic data type. Type `A|B`

represents a type either A or B and you use type guards to examine the type.

However, Union types of TypeScript have more interesting properties combined with structural typing. For example, the type `A|B`

has a property `P`

of type `X|Y`

if `A`

has a property `P`

of type `X`

and `B`

has a property `P`

of type `Y`

. Here an example taken from Spec Preview: Union types.

interface Car { weight: number; gears: number; type: string; } interface Bicycle { weight: number; gears: boolean; size: string; } var transport: Car|Bicycle = /* ... */; var w: number = transport.weight; // OK var g = transport.gears; // OK, g is of type number|boolean console.log(transport.type); // Error, transport does not have 'type' property console.log((<Car>transport).type); // OK

Because both `Car`

and `Bicycle`

types have `weight`

property of `number`

type, you can access `weight`

property of `Car|Bicycle`

type without using a type guard. `gears`

property is more interesting. The type of `gears`

is `number`

in `Car`

and `boolean`

in `Bicycle`

, so the type of `gears`

in `Car|Bicycle`

becomes `number|boolean`

.

Union types also change the algorithm to find the best common type. For example, now TypeScript can infer the type of a mixed array:

var xs = [1,2,3, "hello", "world"];

In old version of TypeScript, the type of `xs`

is `{}[]`

because `number`

and `string`

have nothing in common. But with Union types, the type of `xs`

is inferred as `string|number`

.

In conclusion, Union types provide a succinct way to represent a value with multiple types. They help you keep “DRY principle” by removing all redundant declarations of functions, properties and type constraints.

[…] the previous article, I explained the basics of union types in […]