← the guideMulticore & Missions

§ 02 — Eras · 2012

TypeScript

JavaScript with a contract

Left: era context, features, and the 101 hello. Right: 3 core concepts, 3 deeper 201 lessons, the factorial specimen, and where TypeScript lives today — each column scrolls on its own.

creators
Anders Hejlsberg, Microsoft, 2012
status
alive (dominant) · the default for new web code
lineage
← JavaScript

The problem it solves

JavaScript at scale had no safety net. TypeScript added types that check — then erase — without leaving the ecosystem.

The problem it carries

The types vanish at runtime; any is a trapdoor; and you maintain two languages in your head forever.

Key features

gradual typing
Annotate as much or as little as you like; the annotations vanish at run time.
structural interfaces
Compatibility is by shape, not by declaration — interfaces are structural.
union narrowing
The compiler tracks which cases are possible at each point and rejects the rest.
declaration merging
Types can be extended from other files — the basis of plugins and augmentation.

101 — hello, world

Session one is the smallest program that still counts as speaking TypeScript: what every tutorial prints first, in the dialect that mattered when the language arrived (2012).

the first program2012
const greet = (name: string): string =>
  `Hello, ${name}`;

console.log(greet("world"));

101First contact — hello world and 3 ideas that define how TypeScript reads. 201 — 3 lessons on mechanisms you meet after the factorial specimen: the sharp edges practitioners actually use.

101 — core concepts

3 fragments, each naming a habit of mind in TypeScript. Read the note, then the code — together they are the 101 in one sitting.

01 — annotations

Types that check, then erase — the ecosystem is untouched.

function tally(xs: number[]): number {
  return xs.reduce((a, b) => a + b, 0);
}
tally("123");   // error, at compile time

02 — interfaces

Structural typing: shape matters, declarations don’t.

interface Ship {
  name: string
  tons: number
}
const s: Ship = { name: "Perch", tons: 24 };

03 — narrowing

Unions plus control-flow analysis — invalid states become unrepresentable.

function desc(x: string | number): string {
  return typeof x === "number"
    ? `tons: ${x}`
    : x.toUpperCase();
}

201 — going deeper

The 201 assumes you have read the 101 and the specimen. Each lesson is one mechanism — what it is for, how it looks in code, and the trap or payoff that makes TypeScript distinctive at scale.

  1. generic constraints
  2. conditional and mapped types
  3. narrowing and guards

generic constraints

Constraints describe what a type parameter must provide; without them TypeScript falls back to any, which erases the safety you came for.

function tally<T extends number>(xs: T[]): T {
  return xs.reduce((a, b) => (a + b) as T, 0 as T);
}

conditional and mapped types

Types can branch on other types: mapped types rewrite a shape, template literal types build strings, and conditional types pick a type from another type.

type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
}

narrowing and guards

typeof, in, instanceof and user-defined type predicates all narrow a union — the compiler’s answer to runtime checks.

function isShip(x: unknown): x is Ship {
  return typeof x === "object" && x !== null && "tons" in x;
}

The specimen — factorial

The gradual type: types that check, not obstruct — JavaScript with a contract, adopted by the mainstream without rewriting the world.

the gradual type2012
function tally(xs: number[]): number {
  return xs.reduce((a, b) => a + b, 0);
}
tally("123");  // error: not assignable

Run it today

runbunx tsx fact.ts

Where it is now

Every major frontend codebase and a fast-growing share of backends; the types vanish at runtime.