You now understand why TypeScript exists. Let's look at the building blocks, the basic types that make up everything else. Think of types as labels on boxes. They tell you what's inside so you don't accidentally treat a box of eggs like a box of rocks.
Primitive types
TypeScript extends JavaScript's primitive types with compile-time checking. The main ones you'll use daily are string, number, and boolean.
// Explicit type annotations
let name: string = 'John';
let age: number = 30;
let isActive: boolean = true;
let nothing: null = null;
let notDefined: undefined = undefined;TypeScript is smart enough to infer types from the values you assign:
// Type inference - TypeScript figures it out
let inferredName = 'John'; // TypeScript knows this is string
// inferredName = 42; // Error: Type 'number' is not assignable to type 'string'When to be explicit vs. when to infer:
// Explicit is better for function parameters
function calculateArea(width: number, height: number): number {
return width * height;
}
// Inference is fine for simple constants
const MAX_RETRIES = 3; // TypeScript infers: const MAX_RETRIES: 3Arrays and their types
Arrays in TypeScript need to know what kind of values they hold.
// Two equivalent ways to declare arrays
let numbers: number[] = [1, 2, 3, 4, 5];
let names: Array<string> = ['Alice', 'Bob', 'Charlie'];
// Mixed arrays with union types
let mixed: (string | number)[] = ['one', 2, 'three', 4];| Syntax | Meaning | Example |
|---|---|---|
string[] | Array of strings | ['a', 'b', 'c'] |
number[] | Array of numbers | [1, 2, 3] |
(string \| number)[] | Array of strings OR numbers | ['a', 1, 'b'] |
Array<T> | Generic array syntax | Same as T[] |
Tuples: Arrays with structure
Sometimes you need an array where each position has a specific type. That's a tuple.
let point: [number, number] = [10, 20];
let person: [string, number, boolean] = ['Alice', 30, true];
// TypeScript knows the type at each position
const name = person[0]; // string
const age = person[1]; // numberTuples are perfect for fixed-size collections where order matters:
type HTTPResponse = [number, string];
const success: HTTPResponse = [200, 'OK'];
const notFound: HTTPResponse = [404, 'Not Found'];The danger of any
The any type is an escape hatch. It tells TypeScript: "Don't check this." The problem is, you lose every benefit of TypeScript.
let anything: any = 4;
anything = 'string'; // OK
anything.someMethod(); // OK at compile time - crashes at runtime!When you use any, autocomplete stops working, errors aren't caught, and refactoringWhat is refactoring?Restructuring existing code to make it cleaner, more readable, or more efficient without changing what it does. becomes dangerous. It's contagious too, once a value is any, anything you assign it to becomes any.
unknown: The safe alternative
If you truly don't know a value's type, use unknown instead of any. It forces you to prove what the type is before using it.
let safe: unknown = 4;
// safe.toFixed(); // Error: Object is of type 'unknown'
// You must narrow the type before using it
if (typeof safe === 'number') {
console.log(safe.toFixed(2)); // OK - TypeScript knows it's a number
}Special types: void, never, and literals
// void - function doesn't return anything useful
function logMessage(message: string): void {
console.log(message);
}
// never - function never completes normally
function throwError(message: string): never {
throw new Error(message);
}
// Literal types - a specific value, not just any string
let status: 'loading' | 'success' | 'error' = 'loading';Quick reference
| Type | Description | Example |
|---|---|---|
string | Text values | 'hello' |
number | All numbers (int and float) | 42, 3.14 |
boolean | True or false | true |
any | Opts out of type checking (avoid) | Anything goes |
unknown | Safe unknown, must narrow before use | Requires typeof check |
void | Function returns nothing | console.log |
never | Function never returns | throw new Error() |
T[] | Typed array | number[], string[] |
[T, U] | Tuple, fixed-length, typed positions | [number, string] |
any to silence errors. When AI tools generate TypeScript and hit a type error, they often slap any on the variable to make the error disappear. This defeats the entire purpose of TypeScript. If you see : any in generated code, replace it with the actual type or use unknown and add a type guard. One any can infect an entire call chain.