TypeScript

Sefism.

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, null and undefined are the primitive types. A literal type is one exact value, such as 'GET' or 404.
Why
Literal types let you say "only these values", which turns typos in status codes, event names and modes into compile errors.
TypeScript
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[] (or Array<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.
TypeScript
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 includes undefined, and readonly stops reassignment.
Why
Most application data is objects: API payloads, props, config. Describing them once gives autocomplete and checks everywhere they are used.
TypeScript
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
any switches type checking off for a value. unknown accepts any value but lets you do nothing with it until you narrow it to a specific type.
Why
Use unknown for data from outside (JSON, errors, user input): it forces a check before use. any spreads silently through the code it touches.
TypeScript
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
void means a function returns nothing useful. never is the type with no values: a function that always throws or loops forever returns never, and impossible branches have type never.
Why
never powers exhaustiveness checks and appears when conditional types filter something out; understanding it makes compiler errors readable.
TypeScript
function fail(msg: string): never {
  throw new Error(msg);
}

Strict null checks

Also called strictNullChecks

What
With strictNullChecks (part of strict), null and undefined are separate types that must be listed explicitly, as in string | 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.
TypeScript
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.

01 · Types and the compiler1 / 10