Reference · core type vocabulary
Core type vocabulary — decoder
The six building blocks of Module 1 on one page: type vs interface,
the loose object types, literals/unions vs enum, keyof/typeof/
indexed access, the utility-type catalog, tuples vs arrays, and never. Pin it; print it.
type vs interface (1.1)
| capability | interface | type |
| object / class shape | yes | yes |
| union, tuple, primitive alias | no | yes |
| declaration merging | yes | no |
| extend | extends | & intersection |
Tell: a union/tuple must be a type. A name declared twice
that both survive is an interface (they merge). For a plain object, either works —
reach for interface on shapes, type on everything else.
object vs {} vs Object (1.1)
| you see… | means | accepts |
| object | any non-primitive (lowercase) | objects/arrays/fns — not primitives |
| {} | anything except null/undefined | almost everything, incl. 42, "hi" |
| Object | global wrapper interface (capital O) | nearly everything — avoid; a smell |
let b: object = 42; // ERR — 42 is primitive, not an object
let c: {} = 42; // OK — {} = non-nullish, and 42 qualifies
let d: {} = null; // ERR — null is the one thing {} rejects
Literals, unions vs enum (1.2)
| form | reads as |
| "click" | literal type — the type whose only value is "click" |
| "a" | "b" | "c" | union — a closed set; exactly one of these, nothing else |
| <T extends string> | constraint that preserves the literal instead of widening to string |
String-literal union vs enum: the union is pure type info — erased,
pass the bare string. An enum emits a runtime object you must import
(Dir.Up). Prefer the union for lightness; that’s why most modern code uses it.
function test1<T extends string>(v: T): T { return v; }
const r1 = test1("hello"); // "hello" — literal kept
const r2 = ((v: string) => v)("hello"); // string — widened
keyof / typeof / indexed access (1.3)
| operator | world | reads as |
| typeof x === "…" | value | runtime tag check |
| typeof value | type | lift a value into its static type |
| keyof T | type | union of T’s key names |
| keyof typeof X | type | value → type → union of its keys |
| T[K] | type | indexed access — the type at key K |
function getProperty<T, K extends keyof T>(obj: T, key: K) { return obj[key]; }
type EventMap = { "click": { x: number }; "keydown": { key: string } };
function on<K extends keyof EventMap>(t: K, cb: (e: EventMap[K]) => void) {} // EventMap[K] = exact event
Utility-type catalog (1.4)
| utility | reads as | operates on |
| Partial<T> | every property optional (top level) | object type |
| Record<K,V> | object with keys K, values V | key + value type |
| Pick<T,K> | keep only keys K | object type |
| Omit<T,K> | drop properties K | object type |
| Exclude<U,X> | remove members X | union |
| Extract<U,X> | keep members assignable to X | union |
Omit (object → drop properties) vs Exclude (union → drop members) —
if the first arg is { … } it’s Omit; if it’s A | B it’s
Exclude. Partial is shallow; DeepPartial recurses.
type DeepPartial<T> = { [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P]; };
Partial<Record<Exclude<PluralRule, "other">, string>> // read inside-out: filter → build → loosen
Tuples vs arrays (1.5)
| array T[] | tuple [A, B] |
| length | variable / open | fixed |
| element types | all the same | one per position |
| position matters? | no | yes |
string[] = any-length list of strings · [string] = tuple of exactly
one. A parameter list is a tuple: ...args: [number, string] keeps each
position’s type; ...args: any[] flattens and loses them.
The never type (1.6)
| face | world | behavior |
| exhaustiveness | value | const _x: never = shape fails if a case is unhandled |
| key drop | type | key remapped to never vanishes (string | never = string) |
| narrowing dead-end | error | “not assignable to never” = slot narrowed to nothing |
type PublicUser = { [K in keyof User as K extends "password" ? never : K]: User[K] };
// "password" → never → filtered out of the result
The 3-second checks
- type or interface? Union/tuple →
type. Merges on repeat → interface.
- which
typeof? In a === → value/runtime · after : → value-to-type.
- Omit or Exclude? First arg
{ … } → Omit · first arg A | B → Exclude.
- tuple or array? Several types in order → tuple · one type +
[] → array.
- which
never? Assigned to → guard · produced by a key → drop · in an error → dead-end.