"Two primitives most TypeScript programmers will never type by hand — but you need to recognize both when they appear."
symbol — guaranteed unique identifiers
A symbol is a primitive value that's guaranteed to be unique. Calling Symbol() twice with the same description produces two different symbols. They're most commonly used as object property keys when you need to attach data to an object without colliding with anyone else's keys.
You'll meet symbols most often through the built-in well-known symbols — Symbol.iterator, Symbol.asyncIterator, Symbol.toPrimitive, etc. These are how JavaScript's iteration protocols, primitive coercion, and other meta-behaviors hook into your objects. If you've ever written for (const x of obj), that loop calls obj[Symbol.iterator]() under the hood.
You can declare your own symbols (const TAG = Symbol('Tag')), use them as private-ish property keys, and even type them with the unique symbol type. But day-to-day TypeScript barely touches them directly — they show up most often in the type annotations of library APIs you consume.
bigint — arbitrary-precision integers
JavaScript's number is a 64-bit double, which means integer math past ±2^53 loses precision. bigint is the fix: an arbitrary-precision integer type that handles arithmetic of any size, with the trade-off that you can't mix it with number without an explicit conversion.
You write a bigint literal with an n suffix: const big = 9007199254740993n. Or call BigInt(value). The arithmetic operators work normally between two bigints (big * 2n), but mixing types throws: big + 1 errors at runtime with a TypeError. TypeScript will catch this at compile time if you've annotated correctly.
Use bigint when you need: timestamps in nanoseconds, IDs that exceed Number.MAX_SAFE_INTEGER (database row IDs from systems that use 64-bit identifiers), cryptography, financial calculations that must avoid floating-point error.
string, number, and boolean for the everyday values. symbol and bigint are specialized tools — recognize them, use them when their problem appears, otherwise let them sit in your toolbox.Wrapper objects exist (and you should still avoid them)
Same lowercase-vs-capital rule as the big three: : symbol is the primitive, : Symbol is the wrapper-object constructor type. : bigint primitive, : BigInt wrapper. Always lowercase.