Narrow what a value can be

INPUT · Slides

Check before you use it

01 / 05

First, remember typeof

While it was string | number you could not call a string method on it. But once you have checked, you can.

typeof was the JavaScript way of getting the kind of a value back as text. Text gives you "string", a number gives you "number".

console.log(typeof "Yui");console.log(typeof 7);

Result

string
number

02 / 05

Inside the if it counts as text

Put the result of typeof into the condition of an if and TypeScript treats the inside as "the place where we know it is text". So length becomes available.

The ordinary branching a person would write anyway gets read as type information. This is called narrowing.

function show(m: string | number) {  if (typeof m === "string") {    console.log(m.length);  }}show("panda");

Result

5

03 / 05

The else side becomes a number

If one of the two is ruled out, what is left is the other. So inside the else, m is a number.

Sums like * 2 become writable there.

function show(m: string | number) {  if (typeof m === "string") {    console.log(m + "!");  } else {    console.log(m * 2);  }}show("Yui");show(4);

Result

Yui!
8

04 / 05

Do not check and you get stopped

Write something only one side can do without checking, and you are stopped as before.

When an error appears, take it as a nudge saying "you have not narrowed this down yet". One more if and it goes through.

function show(m: string | number) {  console.log(m * 2);}

Result

Type error: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.

05 / 05

The same trick works on undefined

The same way works on a type meaning "it might not be there yet". Use the contents only inside the check, and write what to do when there is nothing in the else.

Time to write some. Check before you use it — that is all there is to it.

type Name = string | undefined;function call(m: Name) {  if (typeof m === "string") {    console.log("Hi, " + m);  } else {    console.log("no name");  }}call("Yui");call(undefined);

Result

Hi, Yui
no name