Contents

Chapter 2

Your First Type Error

What tsc is actually for.

The error you fixed in chapter 1 was a typo. consol isn’t a word TypeScript knows, so it said so. That’s a useful skill, but it’s not really what TypeScript is for. Plenty of languages catch a misspelled name. What sets TypeScript apart is the thing this chapter is about: it keeps track of what kind of value is sitting inside a name, and it stops you the moment you contradict yourself.

Giving a value a name

let score = 7;

let gives a value a name you can reuse. There’s a lot more to say about it, const in particular, and it’s all coming next chapter. For now, one line is enough: score now stands in for 7 everywhere you use it, the same way name stood in for a string back in chapter 1.

let score = 7;
console.log(score);
7

Nothing new so far. Here’s the part that is.

TypeScript remembers what you gave it

You never wrote the word number anywhere in that line. TypeScript looked at 7, decided score is a number, and it’s not going to forget that decision just because you didn’t write it down yourself.

Try changing what’s inside score:

let score = 7;
score = "seven";
console.log(score);
npx tsc score.ts
score.ts(2,1): error TS2322: Type 'string' is not assignable to type 'number'.

Same shape as chapter 1’s message: a file, a line, a column, and now a code that starts with TS instead of the message speaking for itself. TS2322 is just an ID, TypeScript has a few thousand of these, and you’ll get a feel for the common ones without ever memorising a list. What matters is the sentence after it. score was a number. You handed it a string. TypeScript noticed.

What JavaScript would have let you do

Here’s the sales pitch, and it’s worth seeing directly rather than taking on faith. Open score.js, the file tsc produced:

"use strict";
let score = 7;
score = "seven";
console.log(score);

Run it anyway:

node score.js
seven

It works. JavaScript has no objection to a variable holding a number one moment and a string the next, it just quietly goes along with whatever you last put there. That’s not a defect in JavaScript, it was designed to be forgiving. It’s also exactly how a score variable ends up holding text somewhere deep in a program, and three functions later something tries to do arithmetic on it and gets nonsense instead of an error.

TypeScript’s whole job is catching that before it becomes JavaScript’s problem. The check happens once, while you’re sitting right there looking at the file. The alternative is finding out at 2am, from a bug report, three weeks after you wrote the line, in a function nowhere near the one that actually put the string there in the first place. By then the type is long gone and all you have left is a symptom.

That’s the trade this whole book keeps making, and the reason the two-command loop from chapter 1 exists at all. Plain JavaScript would let you skip straight to node score.js and never know anything was wrong until it broke in some less convenient way, later, somewhere else.

TypeScript doesn’t stop at the first mistake

One more difference worth knowing before the project. In C++, one broken line can make the rest of the file unreadable to the compiler, so you fix the first error and recompile, because the others might not even be real yet. TypeScript’s checker doesn’t work that way. It checks the whole file and tells you everything it found, independent mistakes and all, in one pass:

let score = 7;
let ready = true;
score = "seven";
ready = "yes";
mixed.ts(3,1): error TS2322: Type 'string' is not assignable to type 'number'.
mixed.ts(4,1): error TS2322: Type 'string' is not assignable to type 'boolean'.

Two real, unrelated mistakes, two messages, both trustworthy. Read from the top, fix what you see, and don’t assume a later message will vanish the way it might in C++. It usually won’t, because it was never dependent on the one above it.

Exercise 1 · Two kinds of red

Write a small file with one line like chapter 1’s typo (a misspelled name) and one line like this chapter’s mistake (a value that changes type). Compile it once and look at both messages side by side. One starts with TS2552, one with TS2322. You don’t need to remember the numbers, just notice that they’re not the same complaint wearing different words.

How to look one up

You’ll be searching for these for as long as you write TypeScript, and the code in front of the message makes that easier than it looks. Search TS2322 on its own and you’ll land on pages explaining exactly this error, written by people who hit it before you did. That’s one advantage a numbered code has over free text: two people on opposite sides of the world with completely different variable names still typed the same four characters into the same search box.

The message after the code is still worth reading first, though. Most of the time it already tells you everything: which type you have, which type was expected, and often a suggestion sitting right there in the sentence. The search is for when the message alone doesn’t make it click.

A field guide, two entries so far

CodeWhat it meansYou saw it in
TS2552You referred to a name that doesn’t exist, usually a typoChapter 1
TS2322A value doesn’t match the type its variable already hasThis chapter

Check yourself

1. You run npx tsc on a file with a type error. What happens to the .js file?

Not quite. That is the C++ behaviour, and TypeScript works differently here on purpose to know about.

Yes. Type checking and emitting JavaScript are separate steps, and by default a failed check doesn't cancel the second one.

Not quite. TypeScript does not edit your code for you. What you wrote is what comes out, mistake included.

2. Why did node score.js print "seven" without complaint?

Not quite. Node runs plain JavaScript and JavaScript has no concept of a type mismatch to complain about.

Yes. That check only ever happened in tsc. Once the file is JavaScript, the type is gone and nothing enforces it.

Not quite. Open score.js and look, the mistake is right there, word for word.

3. A file has two unrelated type errors on different lines. What should you expect from tsc?

Not quite. TypeScript checks the whole file in one pass rather than stopping at the first problem.

Yes. Independent mistakes get independent messages. Neither one is waiting on the other to be fixed first.

Not quite. Each mistake gets its own message, at its own line and column.

Project

Fix the profile card

Roughly 20 minutes

Type this out exactly as written, mistakes included, and save it as card.ts:

let studentName = "Ada Lovelace";
let age = 36;
let isMember = true;

console.log(studenName + " is " + age + " years old.");
age = "thirty-six";
isMember = "yes";
console.log("Member:" +isMember);

Compile it:

npx tsc card.ts

You should see three messages. One is a name you’ve met before, the other two are new this chapter. Fix all three, in any order, they don’t depend on each other, and compile again until the output is silent.

Then run it:

node card.js

It runs, and something about the last line still looks wrong. That’s not a type error, and no version of tsc will ever flag it for you, it’s a plain old spacing mistake in how the pieces got joined together. Find it and fix it by eye.

This is worth sitting with for a second: a file with zero type errors is not the same thing as a file that’s right. TypeScript checks what it can check. The rest is still on you.