This episode introduces the alphabet of the TypeScript type system: string, number, boolean, bigint, symbol, null, and undefined. You'll also learn the special types any, unknown, void, and never, plus the difference between annotation and inference.

With the environment ready, we start with the most important foundation: primitive types. Every TypeScript type system, no matter how complex, is built from these building blocks. If episode 0 was environment setup, episode 3 is a mental setup for how types work.
You might think this topic is boring because it looks simple. It's actually the opposite: many production bugs come from misunderstanding the behavior of null and undefined, or from overusing any until the entire type safety collapses.
Episode 3 breaks down every primitive type, the special types for uncertain situations, and the difference between annotation (writing an explicit type) and inference (letting the compiler guess).
The three most frequently used types:
let nama: string = "Arman";
let umur: number = 30;
let aktif: boolean = true;
let harga: number = 4999.99;
let kalimat: string = `Total: ${harga}`;
let sudahBayar: boolean = false;The declaration let umur: number = 30; marks the umur variable as number-only. TypeScript doesn't distinguish between integers and fractions — they're all number. The template literal above is still of type string.
Four other primitives that appear less often:
n suffix.let akunBesar: bigint = 9007199254740993n;
let tombol = Symbol("unik");
let kosong: null = null;
let belumDitetapkan: undefined = undefined;any is the type that disables all checking — the value can hold anything and be used any way. It's occasionally useful during migration (episode 13), but beyond that it destroys every type guarantee.
let dataLonggar: any = "bebas";
dataLonggar.jalanSaja();
let dataTakPasti: unknown = "bisa apa saja";
if (typeof dataTakPasti === "string") {
console.log(dataTakPasti.toUpperCase());
}Note unknown: it's safe because it must be narrowed first before use. unknown is the responsible sibling of any.
function catat(log: string): void {
console.log(log);
}
function gagal(pesan: string): never {
throw new Error(pesan);
}The function gagal(pesan: string): never will never return control to its caller, so its type is never, not void.
You don't always have to write types explicitly:
const harga = 4999; // tipe number disimpulkan
const judul = "Pelajaran"; // tipe string disimpulkan
let mode: "gelap" | "terang" = "gelap";The compiler infers that harga is of type number directly from its initial value. Inference keeps code concise without losing safety. Annotation only becomes necessary when the type can't be inferred, or when you want a type more specific than the initial value.
With strict: true, the strictNullChecks option is enabled: null and undefined cannot be assigned to variables of a normal type. This is the most impactful change for developers coming from JavaScript.
let nama: string = "Arman";
nama = null; // error: null tidak cocok dengan stringErrors like this force you to handle empty cases explicitly — with a string | null union, a typeof guard, or default values. In episodes 4 and 11 we'll discuss the patterns for handling them.
Info
Many developers find strictNullChecks annoying because it surfaces lots of errors. In reality it saves you from the Cannot read properties of null class of bugs that are the most common in JavaScript.
Episode 3 gave you the alphabet of the type system: primitives like string and number, the special types any, unknown, void, and never, and an understanding of when to write annotations and when to rely on inference. You also learned how strictNullChecks works.
Key takeaways:
string, number, boolean, plus bigint, symbol, null, undefined.any disables checking; unknown is safe because it must be narrowed first.void for functions without a value; never for ones that never finish.strictNullChecks prevents null and undefined from slipping in unnoticed.any you use, the stronger your type guarantees.In the next episode 4 we'll discuss union, intersection, and literal types — combining types with | and &, and locking values to specific literals. This is the first tool for modeling real data that comes in varied shapes.