Complete development reference
Development// Primitives
let isDone: boolean = false;
let age: number = 25;
let name: string = "hello";
let big: bigint = 100n;
let sym: symbol = Symbol("id");
// Arrays
let nums: number[] = [1, 2, 3];
let names: Array<string> = ["a", "b"];
// Tuple
let pair: [string, number] = ["age", 25];
let named: [name: string, age: number] = ["Bob", 25];
// Special Types
let anything: any = 42; // Avoid โ disables type checking
let notSure: unknown = 42; // Safe any โ must narrow before use
function fail(): never { throw new Error(); }
function log(): void { console.log("hi"); }
// Null & Undefined
let u: undefined = undefined;
let n: null = null;
// Object & Record
let obj: object = {};
let rec: Record<string, number> = { a: 1 };
// Literal Types
let dir: "north" | "south" | "east" | "west";
let status: 200 | 404 | 500;// Type Assertions
const input = document.getElementById("input") as HTMLInputElement;
// Non-null Assertion
const el = document.getElementById("app")!;
// Custom Type Guard
function isString(val: unknown): val is string {
return typeof val === "string";
}
// typeof narrowing
function process(val: string | number) {
if (typeof val === "string") {
val.toUpperCase(); // string
} else {
val.toFixed(2); // number
}
}
// instanceof narrowing
if (err instanceof Error) console.log(err.message);
// in narrowing
interface Fish { swim(): void; }
interface Bird { fly(): void; }
function move(a: Fish | Bird) {
if ("swim" in a) a.swim();
else a.fly();
}
// Discriminated Unions
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.radius ** 2;
case "square": return s.side ** 2;
}
}
// satisfies (TS 5+)
const palette = {
red: [255, 0, 0],
green: "#00ff00",
} satisfies Record<string, string | number[]>;// Interface
interface User {
readonly id: number;
name: string;
email?: string; // optional
greet(): string;
[key: string]: unknown; // index signature
}
// Extending
interface Admin extends User {
role: "admin" | "superadmin";
}
// Type Alias
type Point = { x: number; y: number };
type ID = string | number;
type Callback = (data: string) => void;
// Intersection
type Employee = User & { department: string };
// Declaration Merging (interface only)
interface Config { debug: boolean; }
interface Config { verbose: boolean; }
// Config now has both debug and verboseinterface for extendable object shapes (supports declaration merging). Use type for unions, intersections, mapped types, and everything else.
// Generic Function
function identity<T>(arg: T): T { return arg; }
const r = identity<string>("hello");
const inferred = identity(42); // T inferred as number
// Constraints
function getLen<T extends { length: number }>(arg: T): number {
return arg.length;
}
// Generic Interface
interface Repo<T> {
find(id: string): Promise<T>;
save(entity: T): Promise<void>;
delete(id: string): Promise<boolean>;
}
// Generic Class
class Stack<T> {
private items: T[] = [];
push(item: T): void { this.items.push(item); }
pop(): T | undefined { return this.items.pop(); }
}
// Multiple Type Parameters
function merge<T, U>(a: T, b: U): T & U {
return { ...a, ...b } as T & U;
}
// Default Type Parameters
interface ApiRes<T = any, E = Error> {
data?: T;
error?: E;
status: number;
}
// keyof constraint
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}| Type | Description | Example |
|---|---|---|
Partial<T> | All properties optional | Partial<User> |
Required<T> | All properties required | Required<User> |
Readonly<T> | All properties readonly | Readonly<User> |
Pick<T, K> | Select subset of keys | Pick<User, "id" | "name"> |
Omit<T, K> | Exclude subset of keys | Omit<User, "email"> |
Record<K, V> | Key-value map type | Record<string, boolean> |
Exclude<U, E> | Remove from union | Exclude<"a"|"b", "a"> โ "b" |
Extract<U, E> | Keep from union | Extract<"a"|"b", "a"> โ "a" |
NonNullable<T> | Remove null/undefined | NonNullable<string | null> |
ReturnType<F> | Function return type | ReturnType<typeof fn> |
Parameters<F> | Function param types | Parameters<typeof fn> |
Awaited<T> | Unwrap Promise type | Awaited<Promise<string>> |
InstanceType<C> | Class instance type | InstanceType<typeof Error> |
// String Enum (preferred)
enum Status {
Active = "ACTIVE",
Inactive = "INACTIVE",
Pending = "PENDING",
}
// Const Enum (inlined at compile time)
const enum Color {
Red = "RED",
Green = "GREEN",
}
// โ
Modern: use 'as const' objects instead of enums
const DIRECTIONS = {
Up: "UP",
Down: "DOWN",
Left: "LEFT",
Right: "RIGHT",
} as const;
type Direction = typeof DIRECTIONS[keyof typeof DIRECTIONS];
// "UP" | "DOWN" | "LEFT" | "RIGHT"// Function Types
type MathOp = (a: number, b: number) => number;
const add: MathOp = (a, b) => a + b;
// Optional & Default Parameters
function greet(name: string, greeting = "Hello"): string {
return `${greeting}, ${name}`;
}
// Rest Parameters
function sum(...nums: number[]): number {
return nums.reduce((a, b) => a + b, 0);
}
// Overloads
function format(value: string): string;
function format(value: number): string;
function format(value: string | number): string {
return typeof value === "string" ? value.trim() : value.toFixed(2);
}
// Generic Arrow (TSX-compatible)
const id = <T,>(arg: T): T => arg;class Animal {
public name: string;
protected species: string;
private _age: number;
readonly id: string;
static count = 0;
constructor(name: string, species: string, age: number) {
this.name = name;
this.species = species;
this._age = age;
this.id = crypto.randomUUID();
Animal.count++;
}
// Getter / Setter
get age(): number { return this._age; }
set age(v: number) { if (v < 0) throw new Error(); this._age = v; }
speak(): string { return `${this.name} makes a sound`; }
}
// Inheritance
class Dog extends Animal {
constructor(name: string, age: number, public breed: string) {
super(name, "Canine", age);
}
override speak() { return `${this.name} barks`; }
}
// Abstract Class
abstract class Shape {
abstract area(): number;
describe() { return `Area: ${this.area()}`; }
}
// Implements Interface
interface Serializable { serialize(): string; }
class Config implements Serializable {
constructor(private data: Record<string, unknown>) {}
serialize() { return JSON.stringify(this.data); }
}// Named Exports
export const PI = 3.14159;
export function add(a: number, b: number) { return a + b; }
export interface Config { debug: boolean; }
// Default Export
export default class Logger { /* ... */ }
// Re-exports
export { default as Logger } from "./logger";
export * from "./utils";
export type { Config } from "./config"; // type-only
// Imports
import Logger from "./logger";
import { add, type Config } from "./utils";
import * as Utils from "./utils";
// Dynamic Import
const mod = await import("./heavy-module");
// Ambient / Global Declarations
declare module "untyped-lib" {
export function doSomething(): void;
}
declare global {
interface Window { myApp: { version: string }; }
}// Class Decorator
function sealed(ctor: Function) {
Object.seal(ctor);
Object.seal(ctor.prototype);
}
@sealed
class Greeter { greeting = "hello"; }
// Method Decorator
function log(target: any, key: string, desc: PropertyDescriptor) {
const orig = desc.value;
desc.value = function(...args: any[]) {
console.log(`Call ${key}`, args);
return orig.apply(this, args);
};
}
class Calc {
@log
add(a: number, b: number) { return a + b; }
}// Mapped Types
type Optional<T> = { [K in keyof T]?: T[K] };
type Nullable<T> = { [K in keyof T]: T[K] | null };
// Template Literal Types
type EventName = `on${Capitalize<"click" | "focus" | "blur">}`;
// "onClick" | "onFocus" | "onBlur"
// Conditional Types
type Flatten<T> = T extends Array<infer U> ? U : T;
// Distributive Conditional
type ToArray<T> = T extends any ? T[] : never;
// ToArray<string | number> โ string[] | number[]
// infer keyword
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
// Recursive Types
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
// Branded / Nominal Types
type USD = number & { __brand: "USD" };
type EUR = number & { __brand: "EUR" };
function usd(n: number): USD { return n as USD; }
// const type parameters (TS 5.0+)
function asConst<const T>(value: T): T { return value; }// Basic async/await
async function fetchUser(id: string): Promise<User> {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
}
// Promise.all โ parallel execution
const [users, posts] = await Promise.all([fetchUsers(), fetchPosts()]);
// Promise.allSettled โ no short-circuit
const results = await Promise.allSettled([a(), b()]);
results.forEach(r => {
if (r.status === "fulfilled") console.log(r.value);
else console.error(r.reason);
});
// Promise.race โ first to settle
const fastest = await Promise.race([a(), b()]);
// Async Generator
async function* paginate<T>(url: string): AsyncGenerator<T[]> {
let page = 1;
while (true) {
const res = await fetch(`${url}?page=${page++}`);
const data: T[] = await res.json();
if (!data.length) break;
yield data;
}
}
for await (const batch of paginate<User>("/api/users")) {
console.log(batch);
}// Custom Error
class AppError extends Error {
constructor(
message: string,
public code: string,
public statusCode = 500
) {
super(message);
this.name = "AppError";
}
}
// Result Type Pattern (no exceptions)
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
function divide(a: number, b: number): Result<number, string> {
if (b === 0) return { ok: false, error: "Division by zero" };
return { ok: true, value: a / b };
}
// Type-safe catch
try {
riskyOp();
} catch (err) {
if (err instanceof AppError) console.error(err.code);
else if (err instanceof Error) console.error(err.message);
else console.error("Unknown", err);
}{
"compilerOptions": {
// Target & Module
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
// Strict (always enable)
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
// Output
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"sourceMap": true,
// Interop
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
// Paths
"baseUrl": ".",
"paths": { "@/*": ["src/*"] },
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}class QueryBuilder<T> {
private filters: Partial<T> = {};
private _limit?: number;
where<K extends keyof T>(key: K, val: T[K]): this {
this.filters[key] = val;
return this;
}
limit(n: number): this { this._limit = n; return this; }
build() { return { filters: this.filters, limit: this._limit }; }
}
const q = new QueryBuilder<User>().where("name", "Bob").limit(10).build();type Events = {
login: { userId: string };
logout: { reason: string };
};
class TypedEmitter<T extends Record<string, any>> {
private listeners = new Map<keyof T, Set<Function>>();
on<K extends keyof T>(event: K, fn: (data: T[K]) => void) {
if (!this.listeners.has(event)) this.listeners.set(event, new Set());
this.listeners.get(event)!.add(fn);
}
emit<K extends keyof T>(event: K, data: T[K]) {
this.listeners.get(event)?.forEach(fn => fn(data));
}
}
const em = new TypedEmitter<Events>();
em.on("login", d => console.log(d.userId)); // fully typed!function assertNever(x: never): never {
throw new Error(`Unexpected: ${x}`);
}
type Action = { type: "inc" } | { type: "dec" } | { type: "reset" };
function reducer(state: number, action: Action): number {
switch (action.type) {
case "inc": return state + 1;
case "dec": return state - 1;
case "reset": return 0;
default: return assertNever(action); // compile error if missed
}
}unknown over anyas const for literal inferencestrict: true alwayssatisfies for type validation without widening