CHAPTER 3 · 5 lessons · 65 exercises
Narrow what a value can be
Allow more than one type, like a string or a number, then check it before you use it and narrow it down.
Every type so far has been "just this one". string means only text, number means only numbers. But in real life there are places where either one is possible.
Take a value someone entered. undefined while nothing has been chosen, text once it has. Or a search that gives you a product when it finds one and null when it does not. What lets you write "A or B" is a union type. You write it by joining types with |, as in string | number.
Write a union type and TypeScript changes its attitude. While both are still possible, it will not let you do something only one of them can do. Try to call toUpperCase() on a string | number and you are stopped, because it would break if the value turned out to be a number. This is not spite — it is showing you a bug that really would happen.
So the next thing you need is narrowing. Write if (typeof x === "string") and inside it TypeScript knows "this is text here". The ordinary branching a person would write anyway gets read as type information. Think of it as the type asking you for the obvious step of checking before you use it.
Unions have one more important use: literal types. Instead of string, you line up the possible values themselves as types, as in "red" | "blue" | "yellow". Written that way, a mistyped string is turned away on the spot. This is the standard move whenever you are dealing with a fixed set of choices.
And then we talk about any and unknown. any is a declaration meaning "any type will do", and writing it makes TypeScript stop looking at that spot entirely. The error goes away, but what went away is the error, not the problem. We cover it not as an escape hatch for when you are stuck, but so that you know why to avoid it.
What you can use instead is unknown. It means "not known yet", and it makes you check before you use it. The difference from any fits in one line: any lets you through without checking; unknown will not let you through until you check. Once you see that difference, what types are for comes properly into view.
The chapter ends with unions of objects. string | number could be told apart with typeof, but that does not work between two objects, because typeof only ever answers "object" for both. So you give each type one marker to tell them apart by. With a marker you can narrow with an if, and inside it you can safely treat the value as one of the two. Real-world data has this shape very often.
By the end of this chapter you will be able to say in a type that "this value could be one of three things" — and, better still, have the machine watch for the case you missed. This is the nicest part of working in a language with types.
Lessons in this chapter
Say it is one of these types
- 13Either type will doJoin types with
|, as instring | number, to write down "it could be either".Go to the exercises - 14Allow only certain valuesMake the values themselves into a type, as in
"red" | "blue", and catch typos on the spot.Go to the exercises
Check before you use it
- 15Check before you use itNarrow it down with
if (typeof x === "string")and use it as one of the two types inside.Go to the exercises - 16Avoid any, use unknown
anyswitches the checking off. Take a value you do not know withunknownand check it before you use it.Go to the exercises
Tell objects apart
- 17Unions you tell apart by a markerGive each type a shared marker property so you can tell unions of objects apart with an
if.Go to the exercises