Chapter 01
Types and the compiler
What TypeScript is, what the compiler does with your code and the handful of types everything else is built from.
Type checking and type erasure
Also called tsc, TS
- What
- TypeScript is JavaScript plus a static type system. The compiler (
tsc) checks the types, then removes them and emits plain JavaScript; types never exist at runtime. - Why
- You get errors in the editor before the code runs, and safe refactors across a large codebase, while shipping ordinary JavaScript.
Watch out
Expecting types to check data at runtime: a value typed User from JSON.parse is unchecked until you validate it.
Primitive and literal types
- What
string,number,boolean,bigint,symbol,nullandundefinedare the primitive types. A literal type is one exact value, such as'GET'or404.- Why
- Literal types let you say "only these values", which turns typos in status codes, event names and modes into compile errors.
let count: number = 0;
type Method = 'GET' | 'POST' | 'DELETE';
const method: Method = 'GET';
const code: 200 | 404 = 404;Watch out
Using the wrapper types String, Number or Object in annotations; always use the lowercase primitives.
Arrays, tuples and readonly arrays
- What
string[](orArray<string>) is a list of any length. A tuple such as[string, number]has a fixed length with a type per position.readonly string[]forbids mutation.- Why
- Tuples model pairs like
[key, value]and hook return values; readonly arrays document that a function will not change what it is given.
const tags: string[] = ['ts', 'js'];
const entry: [string, number] = ['age', 42];
function total(xs: readonly number[]) {
return xs.reduce((a, b) => a + b, 0);
}Watch out
Indexing past a tuple or array still types as the element type unless noUncheckedIndexedAccess is on.
Object types and optional properties
- What
- An object type lists property names and their types.
?marks a property as optional, so its type also includesundefined, andreadonlystops reassignment. - Why
- Most application data is objects: API payloads, props, config. Describing them once gives autocomplete and checks everywhere they are used.
type Post = {
readonly id: string;
title: string;
tags?: string[];
};Watch out
Marking everything optional to silence errors, which pushes undefined checks into every caller.
any and unknown
- What
anyswitches type checking off for a value.unknownaccepts any value but lets you do nothing with it until you narrow it to a specific type.- Why
- Use
unknownfor data from outside (JSON, errors, user input): it forces a check before use.anyspreads silently through the code it touches.
function parse(raw: string): unknown {
return JSON.parse(raw);
}
const data = parse('{"n":1}');
if (typeof data === 'object' && data !== null) {
console.log('n' in data);
}Watch out
Reaching for any to fix a hard error; it hides the error and every later one that value causes.
never and void
- What
voidmeans a function returns nothing useful.neveris the type with no values: a function that always throws or loops forever returnsnever, and impossible branches have typenever.- Why
neverpowers exhaustiveness checks and appears when conditional types filter something out; understanding it makes compiler errors readable.
function fail(msg: string): never {
throw new Error(msg);
}Strict null checks
Also called strictNullChecks
- What
- With
strictNullChecks(part ofstrict),nullandundefinedare separate types that must be listed explicitly, as instring | null, and handled before use. - Why
- It removes the most common runtime error in JavaScript, reading a property of
undefined, by making the compiler ask where a missing value is handled.
function initials(name: string | null) {
return name?.slice(0, 2).toUpperCase() ?? '??';
}Watch out
Sprinkling the non-null assertion ! to silence these errors instead of handling the missing case.