TypeScript Cheatsheet: Types, Interfaces, Generics and Utility Types
TypeScript reference for working code: primitive and union types, interfaces vs type aliases, generics with constraints, and the utility types you will actually use.
1. Basic Types and Annotations
Annotate function boundaries and let inference do the rest. The three special types matter most: unknown forces a check before use, any opts out of checking entirely, and never means "this cannot happen".
let name: string = "Ana";
let scores: number[] = [10, 20];
let pair: [string, number] = ["id", 42]; // tuple
let status: "idle" | "loading" | "done" = "idle"; // literal union
let data: unknown; // safe: must narrow before use
let anything: any; // escape hatch: no checking at all
function greet(user: string, loud = false): string {
return loud ? `HELLO ${user}` : `Hello ${user}`;
}
// Narrowing: checks that refine a union
function printId(id: string | number) {
if (typeof id === "string") return id.toUpperCase();
return id.toFixed(0);
}
2. Interfaces and Type Aliases
Interfaces describe object shapes and can be extended and merged; type aliases cover unions, tuples and computed types. For public object shapes, interface is the common default.
interface User {
id: number;
email: string;
nickname?: string; // optional property
readonly createdAt: Date; // set once, never reassigned
}
interface Admin extends User {
permissions: string[];
}
type Result<T> = { ok: true; value: T } | { ok: false; error: string };
type ID = string | number;
const u: User = { id: 1, email: "[email protected]", createdAt: new Date() };
3. Generics: Reusable, Type-Safe Code
A generic captures the type relationship between inputs and outputs instead of hard-coding one type. Constraints (extends) promise just enough structure for the body to work.
// One function, every element type
function first<T>(items: T[]): T | undefined {
return items[0];
}
const n = first([1, 2, 3]); // number | undefined
const s = first(["a", "b"]); // string | undefined
// Constraint: T must at least have a length
function longest<T extends { length: number }>(a: T, b: T): T {
return a.length >= b.length ? a : b;
}
// keyof: keys of a type, for safe property access
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
4. Utility Types You Will Actually Use
These built-ins transform existing types instead of duplicating them. They are generic under the hood and appear in almost every production codebase.
| Utility | Transforms | Typical use |
|---|---|---|
Partial<T> | Every property becomes optional | Update payloads |
Required<T> | Every property becomes required | Fully-populated config objects |
Pick<T, K> | Keeps only the listed keys | DTOs and API responses |
Omit<T, K> | Removes the listed keys | Create payloads without an id |
Record<K, V> | Object with keys K and values V | Dictionaries and lookup maps |
ReturnType<fn> | The return type of a function type | Typing derived results |
Awaited<T> | Unwraps a Promise to its resolved type | Async function results |
NonNullable<T> | Removes null and undefined | After a guard or filter |
π Associated Learning Path & Monetization Blueprints
TypeScript Enterprise Architecture and Generics
Scale these patterns to enterprise codebases: architecture, advanced generics and strict configs.
Read Full Guide βLegacy Code Modernization
Migrate JavaScript codebases to strict TypeScript for business clients.
Read Blueprint βNeed another cheat sheet?
We add new reference guides every week based on community requests.
Request a Cheatsheet β