Typescript Union Types

Driven professional with expertise in problem-solving, relationship building, and event organization, complemented by a strong presence in blogging and public speaking. Currently studying Frontend Development Career Path from Scrimba and working as Program Manager at MongoDB. I am actively looking to switch to a more technical profile and build web solutions. I bring great leadership, program management and customer engineering background, that proves my strong interpersonal, team building and resourceful skills
TypeScript lets us type variables with different levels of type specificity. If the type is defined as string, number it becomes very specific type since Typescript will allow variable to have only string or a number value respectively. We could also type a variable as any which isvery unspecific and allow value of any type without complaining or throwing an error.
To strike a balance between extreme specificity and being totally unspecific with types, Typescript allows u sto be flexible with how specific our types are by combining different types. When we combine types, it is called a union.
Defining Unions
Unions allow us to define multiple allowed type members by eparating each type member with a vertical line character|.
let ID: string | number;
// number
ID = 1;
// or string
ID = '001';
console.log(`The ID is ${ID}.`);
In this example, string | number is a union that allows ID to be a string or a number. It’s more flexible than a single primitive type, but much more specific than the any type.
Type Narrowing
Typing with unions gives us more flexibility with type specificity, but you need to perform different logic based on the type using a type guard. A type guard is a conditional that checks if a variable is a certain type, like this:
function getMarginLeft(margin: string | number) {
// margin may be a string or number here
if (typeof margin === 'string') {
// margin must be a string here
return margin.toLowerCase();
}
}
If you tried to call margin.toLowerCase() outside of the string type guard, TypeScript would complain that the .toLowerCase() method does not exist on number types. This error would occur because margin is typed as a string | number union.
This concept is called type narrowing. Type narrowing is when TypeScript can figure out what type a variable can be at a given point in our code. Type narrowing allows us to use unions, then perform type-specific logic without TypeScript getting in the way.
function formatValue(value: string | number) {
// Write your code here
if(typeof value === 'string') {
console.log(value.toLowerCase())
}
if(typeof value === 'number') {
console.log(value.toFixed(2))
}
}
formatValue('Hiya');
formatValue(42);
Inferred Union Return Types
One of the awesome things about TypeScript is that it’s able to infer types in many cases. A great example is a function’s return type. TypeScript will look at the contents of a function and infer which types the function can return. If there are multiple possible return types, TypeScript will infer the return type as a union.
function getBook() {
try {
return getBookFromServer();
} catch (error) {
return `Something went wrong: ${error}`;
}
}
If the call is successful, the function will return a Book type describing a book. If the call fails, the function will return a string. getBook() can return a Book or string type, TypeScript infers the return type as the union Book | string. Since TypeScript can infer the function’s return type, there’s no need for us to manually define it.
Unions and Arrays
Unions are even more powerful when used in combination with arrays. To create a union that supports multiple types for an array’s values, wrap the union in parentheses (string | number), then use array notation [].
function formatListings(listings: (string | number)[]) {
return listings.map((listing) => {
if (typeof listing === 'string') {
return listing.toUpperCase();
}
if (typeof listing === 'number') {
return `$${listing.toLocaleString()}`;
}
});
}
const result = formatListings([
'123 Main St',
226800,
'580 Broadway Apt 4a',
337900,
]);
console.log(result);
The parentheses are vitally important to type arrays correctly. If we left out the parentheses and wrote string | number[], that type would allow strings or arrays of only numbers.
Common Key Value Pairs
When we put type members in a union, TypeScript will only allow us to use the common methods and properties that all members of the union share.
const batteryStatus: boolean | number = false;
batteryStatus.toString(); // No TypeScript error
batteryStatus.toFixed(2); // TypeScript error
Since batteryStatus can be a boolean or a number, TypeScript will only allow us to call methods that both number and boolean share. They both share .toString(), so we’re good there. But, since only number has a .toFixed() method, TypeScript will complain if we try to call it.
The rule also applies to type objects that we define.
type Goose = {
isPettable: boolean;
hasFeathers: boolean;
canThwartAPicnic: boolean;
}
type Moose = {
isPettable: boolean;
hasHoofs: boolean;
}
const pettingZooAnimal: Goose | Moose = { isPettable: true };
console.log(pettingZooAnimal.isPettable); // No TypeScript error
console.log(pettingZooAnimal.hasHoofs); // TypeScript error
Any properties or methods that are not shared by all of the union’s members won’t be allowed and will produce a TypeScript error
Unions with Literal Types
Literal type unions are useful when we want to create distinct states within a program. For example, a traffic light control program:
type Color = 'green' | 'yellow' | 'red';
function changeLight(color: Color) {
// ...
}
With the code above, we could ensure that wherever changeLight() is called, that it gets passed only allowed stoplight colors. If we tried to call changeLight('purple'), TypeScript would complain, since that is not a valid stoplight color.
This technique allows us to write functions that are specific about the states they can handle, which helps us write code that’s less prone to errors.
Note: These are my notes as I go along doing Typescript on Codecademy. I hope they are useful to you as they are to me!



