"Every program is a graph of three primitives and a few special cases. Start with the three."
The shape of the big three
Every TypeScript program is, at the bottom, a graph of string, number, and boolean values. Most other types you'll meet are containers, shapes, or unions of these.
The annotations are spelled in lowercase: string, number, boolean. Never String, Number, Boolean — those are the JavaScript wrapper-object constructors, and you almost never want them as types. The lowercase forms are the primitive types you actually want.
string — UTF-16 by default
The string type covers every JavaScript string: single quotes ('hi'), double quotes ("hi"), or template literals (`hi ${name}`). All three produce values of type string. The three syntactic forms exist for taste and templating, not for type distinctions.
JavaScript strings are UTF-16 internally. That detail rarely matters until you handle non-BMP characters (most emoji, some CJK ideographs) — there, you'll see '😀'.length === 2 because the emoji is a surrogate pair. Use [...str] or Array.from(str) to iterate by code point instead of code unit when this matters.
number — IEEE 754 double, no integer type
TypeScript's number is JavaScript's number: a 64-bit IEEE 754 double-precision float. There is no separate integer type. 1, 1.5, NaN, Infinity, -0 are all of type number. The full range of safe integers is ±2^53 − 1 (use Number.MAX_SAFE_INTEGER to spell it). Past that, integer arithmetic loses precision — that's what bigint is for, which we cover in a later lesson.
Don't try to introduce an int type alias and pretend the runtime will enforce it. The type system doesn't distinguish; the runtime doesn't either. If you need integer arithmetic with guarantees, use bigint or guard your own boundaries.
boolean — just true and false
boolean has two values. Nothing surprising here. The only thing to watch is JavaScript's coercion rules at runtime (if ('') /* falsy */, if (0) /* falsy */, if ('false') /* truthy! */) — these still apply when your boolean is computed from a string or number expression. TypeScript will warn under strict mode if you compare boolean to something incompatible, but it can't catch every coercion mistake.
: string is the primitive type. : String is the wrapper-object type — different, almost never what you want, and lint rules will flag it. The lowercase forms are what every TypeScript style guide and the official Handbook use.Pippa's confession
Date.now() (number, milliseconds since epoch). Names are strings. Flags are booleans. The fancy types — BrainName, ConversationId, SoulId — are all built on top of these three, narrowed down with literal types or generics. The primitives are the ground floor; everything above is decoration.