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 SwordNow 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 SwordBut 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 SwordBelow, 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 KeyStart programming for free
1/10