TypeScript adds types on top of JavaScript's runtime values. Types describe what shape data has — is it a string? A number? An array of objects? The compiler uses these descriptions to catch mistakes.
Primitive Types
TypeScript has six primitive types that map directly to JavaScript:
| Type | Example | Notes |
|---|---|---|
string |
"Hello" |
Text — single, double or backtick quotes |
number |
42, 3.14, 0xff |
Integers and floats — no distinction |
boolean |
true, false |
Logical values |
null |
null |
Intentional absence of value |
undefined |
undefined |
Uninitialised variable |
bigint |
42n |
Arbitrary-precision integers |
symbol |
Symbol("id") |
Unique, immutable identifiers |
let name: string = "Sita";
let age: number = 21;
let isStudent: boolean = true;
let nothing: null = null;
let notDefined: undefined = undefined;Type Inference
You do not always need to write the type. TypeScript infers it from the value:
let x = 42; // inferred as number
let text = "hello"; // inferred as string
let flag = true; // inferred as booleanWhen to annotate: always annotate function parameters and return types. For local variables, let inference do the work unless the type is not obvious.
// ✅ Good — inference is clear
const items = [1, 2, 3];
// ✅ Good — annotate parameters and return
function add(a: number, b: number): number {
return a + b;
}
// ❌ Unnecessary — the type is obvious from the literal
const name: string = "Sita";Arrays
TypeScript has two syntaxes for arrays:
// Syntax 1: type[]
let numbers: number[] = [1, 2, 3];
let names: string[] = ["Ram", "Shyam"];
// Syntax 2: Array<type> (generic syntax)
let scores: Array<number> = [85, 92, 78];Both are identical — use whichever you prefer. The type[] syntax is
more common.
Tuples
A tuple is a fixed-length array where each position has a known type:
// A pair of [city, population]
let pair: [string, number] = ["Kathmandu", 1_400_000];
// Destructuring works naturally
let [city, pop] = pair;Tuples are useful for returning multiple values from a function:
function getState(): [string, string] {
return ["Bagmati", "Nepal"];
}
let [province, country] = getState();Enums
Enums give a friendly name to a set of numeric or string values:
// Numeric enum (default — auto-increments from 0)
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right, // 3
}
let move: Direction = Direction.Up;
console.log(move); // 0String enums are often clearer and safer:
enum Status {
Active = "ACTIVE",
Inactive = "INACTIVE",
Banned = "BANNED",
}
function handleStatus(status: Status) {
// TypeScript ensures only valid values are passed
}| Enum type | Values | When to use |
|---|---|---|
| Numeric | 0, 1, 2, ... |
Rarely — use string enums instead |
| String | "ACTIVE", "INACTIVE" |
Most cases — debuggable, serialisable |
Special Types
TypeScript has four special types that behave differently:
| Type | Meaning | Example |
|---|---|---|
any |
Opt out of type checking — avoid | let x: any = 42 |
unknown |
Like any but forces you to narrow before use |
let x: unknown = 42 |
void |
Function returns nothing | function log(msg: string): void |
never |
Function never returns (throws or loops forever) | function die(msg: string): never |
// unknown — safe alternative to any
function process(value: unknown) {
if (typeof value === "string") {
console.log(value.toUpperCase()); // ✅ safe — TypeScript knows it's a string
}
}
// void — function with no return value
function greet(name: string): void {
console.log(`Hello, ${name}`);
}
// never — function that always throws
function throwError(msg: string): never {
throw new Error(msg);
}Array Helper Types
TypeScript provides utility types for arrays:
// Readonly — cannot add, remove or change elements
let frozen: readonly number[] = [1, 2, 3];
// frozen.push(4); // Error
// Tuple with optional elements
let point: [number, number, number?] = [10, 20]; // third is optionalTips
- Never use
anyin production code — it defeats the purpose of TypeScript. Useunknowninstead and narrow the type. - Prefer
constfor variables — TypeScript narrowsconstvalues more aggressively. - Use
readonlyarrays and objects when you do not want mutation.
Common Mistakes
// ❌ Mixing types in an array — use (string | number)[] instead
let mixed: string[] = ["hello", 42]; // Error
// ❌ Using any — use unknown instead
let danger: any = "hello";
danger.nonExistentMethod(); // Compiles but crashes at runtime
// ✅ Correct
let safe: unknown = "hello";
if (typeof safe === "string") {
safe.toUpperCase(); // Safe
}Next: how to describe the shape of objects with interfaces.