DAY 14 OF 30
Narrowing in TypeScript
Yesterday, in one sentence
A colon after each parameter name, and a colon after the brackets for the return type. Parameters must be annotated, the return type is usually inferred.
Did you say:
- ✓a colon after each parameter name
- ✓a colon after the brackets for the return type
- ✓parameters must be annotated, the return type is usually inferred
Interview question
Put a ? after the parameter name. The caller can leave the argument out, so
inside the function it is the declared type or undefined.
Did you say:
- ✓a `?` after the parameter name
- ✓the argument can be left out
- ✓the type is the declared type or `undefined`
A union typeUnion Type says a value could be one of several types. When passed as a function parameter, TypeScript does not know which one it is yet, so it reports an error on anything that would fail for one of them.
function describe(id: string | number) {
id.toUpperCase();
// ❌ Property 'toUpperCase' does not exist on type 'string | number'
// id might be a number, and numbers have no toUpperCase method
}
Narrowing is when TypeScript works out from your code that a value must be one specific type in that part of the program. Once you have narrowed the type, TypeScript allows you to use it.
You can use typeof to return a string describing the value's type, and TypeScript
narrows from that check. This is known as a type guard, which is covered in the next
lesson.
function describe(id: string | number) {
if (typeof id === "string") {
id.toUpperCase(); // id is string here
} else {
id.toFixed(2); // id is number here
}
}
The in operator checks whether a property name exists on a value, which narrows an object typeObject Type.
type Hero = { power: string };
type Villain = { scheme: string };
function act(character: Hero | Villain) {
if ("power" in character) {
character.power; // character is Hero here
} else {
character.scheme; // character is Villain here
}
}
Checking for undefined narrows too, which is how you handle an optional property or
parameter.
function recruit(team?: string) {
if (team === undefined) return;
team.toUpperCase(); // team is string here
}
Check yourself
value on the marked line?
function show(value: string | number | boolean) {
if (typeof value === "number") return
if (typeof value === "boolean") return
value // ← here
}
Each check returns early, so by the last line TypeScript has ruled out number and boolean and only string is left.
When TypeScript works out from your code that a value must be one specific type in that part of the program.
Did you say:
- ✓TypeScript works out the specific type from your code
- ✓applies to that part of the program