C.W.K.
Stream
Lesson 01 of 05 · published

The Big Three Primitives: string, number, boolean

~10 min · primitives, string, number, boolean

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"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.

Lowercase primitives, not wrapper classes: : 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

Every primitive in cwkPippa's frontend is one of these three. Times come from 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.

Code

Lowercase primitives, not capitalized wrappers·typescript
// The three primitives, every shape.

const name: string = 'Pippa';
const alt: string = `Hi, ${name}`;          // template literal — still string
const escaped: string = "don't quote me";   // single, double, template — all string

const age: number = 21;
const pi: number = 3.14159;
const broken: number = NaN;                  // still number
const max: number = Number.MAX_SAFE_INTEGER; // 2^53 - 1

const online: boolean = true;
const inverse: boolean = !online;            // false

// Common mistake — the wrapper-object type:
const wrong: String = 'Pippa';               // ⚠️ compiles, but lint will flag
// Always use the lowercase primitive form: string, number, boolean.
Two number gotchas every TS dev should hit once early·typescript
// Two number gotchas worth knowing early.

// 1. No integer type — everything is a double.
const tiny = 0.1 + 0.2;                      // 0.30000000000000004 — IEEE 754 reality

if (tiny === 0.3) {
  // ❌ never reached
} else {
  console.log('Floats lie. Use Number.EPSILON for comparisons.');
}

// 2. NaN never equals NaN.
const notANumber = NaN;
if (notANumber === NaN) {
  // ❌ never reached — NaN !== NaN by spec
}
if (Number.isNaN(notANumber)) {
  // ✅ this is how you actually check
}

External links

Exercise

Write a function formatPrice(amount: number, currency: string): string that returns a string like '$12.34'. Now hover the return type to confirm inference. Then try calling it with formatPrice('12', 'USD') — what does the compiler say? Why is that error message exactly what we wanted from TypeScript?
Hint
The compiler will tell you that argument 1 should be number, not string. That's the entire pitch of TypeScript in one error message — a runtime bug caught at compile time. Take a second to appreciate it.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue
💛 by Ttoriwarm

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.