Union Types

Not every value has just one type. When Kira finishes a quest, her reward is sometimes gold, a number like 50, and sometimes an item, a text like "Silver Sword". With the types you know so far, one variable can't hold both:

let reward = 50;
reward = "Silver Sword";
main.ts(2,1): error TS2322: Type 'string' is not assignable to type 'number'.

For values like this, TypeScript has union types. You write several types with a vertical bar | between them, and you read the bar as “or”: number | string is “a number or a text”.

let reward: number | string = 50;
console.log(reward);
reward = "Silver Sword";
console.log(reward);

This prints:

50
Silver Sword

Now reward may hold a number or a text, but still nothing else. If you add the line reward = true; at the end, TypeScript reports:

main.ts(5,1): error TS2322: Type 'boolean' is not assignable to type 'string | number'.

In the message, the union is written as string | number, although the code says number | string. The order doesn't matter: both mean the same type. A union may also have more members, such as string | number | boolean. And you've met a union before: an optional parameter title?: string has the type string | undefined.

Unions are most useful for parameters. This function accepts both kinds of reward:

function showReward(reward: string | number): void {
    console.log(`Your reward: ${reward}`);
}

showReward(50);
showReward("Silver Sword");

This prints:

Your reward: 50
Your reward: Silver Sword

But what may the function do with reward? Only what works for every type in the union. Printing works for numbers and texts alike, and so does a template literal. A text method doesn't:

function shoutReward(reward: string | number): string {
    return reward.toUpperCase();
}
main.ts(2,19): error TS2339: Property 'toUpperCase' does not exist on type 'string | number'.
  Property 'toUpperCase' does not exist on type 'number'.

This message has two lines. The first one says that the union string | number has no toUpperCase, and the indented second line tells you why: number doesn't have it. TypeScript can't know which type the function will get when it runs. If it got 50, JavaScript would crash with TypeError: reward.toUpperCase is not a function. So TypeScript allows only what is safe for both types. Arithmetic is the same: reward * 2 is an error too, because the reward might be a text.

In the next exercise, you'll learn how to find out which type a value has, so that you can use text methods on texts and arithmetic on numbers.

Typical mistake: two bars instead of one. In types, the bar is single; let reward: number || string = 50; isn't valid TypeScript, and the compiler gets lost:

main.ts(1,20): error TS1005: ',' expected.
main.ts(1,30): error TS1005: ';' expected.

Instructions

Run the program: TypeScript doesn't let you store a text in reward. Change the type of reward to the union of number and string, so that the program prints:

Reward: 50
Reward: Silver Sword

Below, write a function announce with one parameter, reward, of the type string | number. The function prints Quest complete! Reward: followed by the reward.

Call announce twice: with 120 and with "Old Key". The program then prints:

Reward: 50
Reward: Silver Sword
Quest complete! Reward: 120
Quest complete! Reward: Old Key

Start programming for free

By signing up, you agree to the Terms of Service and Privacy Policy.

Or sign up with:

1/10