Short answer: TypeScript adds static types to JavaScript: annotate with let port: number, describe objects with interface or type, combine types with unions (|) and narrow them with typeof or a kind field. Generics (<T>) and utility types such as Partial, Pick and Record remove repetition. The current release is TypeScript 7.0, a native compiler that is about ten times faster and uses strict by default.
The examples in this TypeScript cheat sheet were type-checked with TypeScript 7.0.2 (strict on) and the output run with Node.js 24.21.0 on 9 October 2026. Lines marked as errors were confirmed with // @ts-expect-error.
Table of Contents
Basic types and annotations
| Syntax | What it means |
|---|---|
let host: string = "web01" | Explicit annotation |
let port = 443 | Inferred as number; annotate only where inference is not enough |
const ids: number[] = [1, 2] · Array<string> | Arrays, two equivalent spellings |
const pair: [string, number] = ["db01", 3306] | Tuple: fixed length and position types |
let maybe: string | undefined | Union: either type |
unknown | Any value, but you must narrow it before use. Prefer it to any |
any | Turns type checking off for that value |
void | Function returns nothing useful |
never | Never returns (always throws), or an impossible case |
value as Server | Type assertion: you tell the compiler, it does not check at run time |
value! | Non-null assertion: removes null and undefined. Use sparingly |
let port = 443;
port = "80"; // error TS2322: Type 'string' is not assignable to type 'number'.
Interfaces and type aliases
interface Server {
readonly id: number; // cannot be reassigned
name: string;
ip: string;
port?: number; // optional: number | undefined
}
interface WebServer extends Server {
vhosts: number;
}
type Status = "up" | "down" | "maint"; // literal union
type Point = { x: number; y: number };
type Tagged = Server & { tags: string[] }; // intersection
Both describe object shapes. Use interface for objects you may extend or merge, and type for unions, tuples, function types and computed types. A readonly property only stops reassignment through that type; it does not freeze the object.
Unions and narrowing
| Pattern | Example |
|---|---|
typeof check | if (typeof v === "number") return v.toFixed(1); |
in check | if ("ip" in x) { ... } |
instanceof | if (e instanceof Error) console.error(e.message); |
Truthiness and ?. · ?? | const len = maybe?.length ?? 0; |
| Discriminated union | type Result = { ok: true; value: number } | { ok: false; error: string } |
| Type guard function | function isServer(x: unknown): x is Server { ... } |
A shared literal property (kind below) lets the compiler narrow each case, and the never assignment fails to compile if someone adds a new shape without handling it:
type Shape = { kind: "circle"; r: number } | { kind: "square"; side: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.r ** 2;
case "square": return s.side ** 2;
default: {
const _exhaustive: never = s;
return _exhaustive;
}
}
}
Functions and generics
| Syntax | What it does |
|---|---|
function connect(host: string, port = 22, ...opts: string[]): string | Typed parameters, default, rest and return type |
const add = (a: number, b: number): number => a + b | Typed arrow function |
type Handler = (event: string) => void | Function type |
function first<T>(items: T[]): T | undefined | Generic: the type flows from the argument |
<T extends { length: number }> | Constraint: T must have a length |
<T, K extends keyof T>(obj: T, key: K): T[K] | Typed property access; a wrong key is a compile error |
function parse(v: string): number; function parse(v: number): string; | Overload signatures, followed by one implementation |
async function getJson<T>(url: string): Promise<T> | Async functions return Promise<T> |
Classes
abstract class Base {
protected abstract kind: string;
describe(): string { return `I am ${this.kind}`; }
}
class Db extends Base {
protected kind = "db";
#password = "x"; // JavaScript private field (enforced at run time)
static count = 0;
constructor(public readonly name: string, private port: number = 3306) {
super(); // parameter properties create this.name and this.port
Db.count++;
}
get dsn(): string { return `${this.name}:${this.port}`; }
override describe(): string { return super.describe() + " " + this.dsn; }
}
private and protected are checked only at compile time; #field is private at run time too. Parameter properties (public name in the constructor) are not erasable syntax, so Node.js cannot run them directly from a .ts file (see the last section).
Utility types
| Type | Result |
|---|---|
Partial<Server> | Every property optional (good for PATCH payloads) |
Required<Server> | Every property required |
Readonly<Point> | Every property readonly |
Pick<Server, "name" | "ip"> | Only those properties |
Omit<Server, "id"> | All except those properties |
Record<Status, string[]> | Object with exactly those keys |
Exclude<Status, "maint"> · Extract<Status, "up"> | Remove from · keep from a union |
NonNullable<string | null> | Drop null and undefined |
ReturnType<typeof fn> · Parameters<typeof fn> | Return type · parameter tuple of a function |
Awaited<Promise<number>> | The resolved type: number |
keyof, typeof, mapped and conditional types
| Syntax | What it does |
|---|---|
const d = { host: "localhost", port: 3306 } as const | Literal, readonly types for the whole object |
typeof d · keyof typeof d | Type of a value · its keys as a union ("host" | "port") |
Server["ip"] | Indexed access: the type of one property |
(typeof levels)[number] | Union of an as const array’s items |
{ [K in keyof T]: T[K] | null } | Mapped type: transform every property |
T extends string ? "yes" : "no" | Conditional type |
T extends (infer U)[] ? U : never | infer: extract a type from inside another |
`${"dev" | "prod"}-${"eu" | "us"}` | Template literal type: four allowed strings |
obj satisfies Record<string, `/${string}`> | Check against a type but keep the narrower inferred type |
tsconfig and the compiler
| Command or option | What it does |
|---|---|
npm install -D typescript | Installs TypeScript 7 (the native, Go-based compiler) in the project |
npx tsc --init | Write a starter tsconfig.json |
npx tsc · npx tsc --noEmit · npx tsc -w | Build · type-check only · watch |
"strict": true | All strict checks. Default since TypeScript 6.0 |
"noUncheckedIndexedAccess": true | rec[key] becomes T | undefined |
"module": "nodenext" | Correct ESM and CommonJS rules for Node.js |
"rootDir": "./src" · "outDir": "./dist" | Input and output folders. Set rootDir explicitly in 7.0 |
"types": ["node"] | Global type packages. The default is now [], so list the ones you need |
"erasableSyntaxOnly": true | Reject enums, namespaces and parameter properties |
--checkers 2 · --singleThreaded | Control parallel type-checking (TypeScript 7) |
TypeScript 7 adopts the 6.0 defaults and turns 6.0 deprecations into errors: target: es5, baseUrl, moduleResolution: node and the AMD, UMD and SystemJS module formats are gone. Tools that still need the old compiler API, such as typescript-eslint, can use the @typescript/typescript6 package side by side.
For server admins: config files and running .ts in Node.js
JSON from a file or an API is unknown until you check it. Validate the fields you need instead of casting blindly:
interface AppConfig { host: string; port: number; replicas?: string[] }
function loadConfig(text: string): AppConfig {
const data: unknown = JSON.parse(text);
if (typeof data !== "object" || data === null) throw new Error("config must be an object");
const { host, port } = data as Record<string, unknown>;
if (typeof host !== "string" || typeof port !== "number") {
throw new Error("host and port are required");
}
return data as AppConfig;
}
Node.js 24 runs a .ts file directly (node check.ts) by stripping the types, without type-checking. It accepts only erasable syntax: an enum or a constructor parameter property makes it fail with a syntax error. Run npx tsc --noEmit in CI for the type check, and set erasableSyntaxOnly so the editor flags code that Node.js cannot strip. For large scripts, compile with tsc and run the JavaScript in dist/.
Official documentation (checked 9 October 2026): The TypeScript Handbook · Utility Types · TSConfig Reference · Announcing TypeScript 7.0 · Node.js v24: Modules: TypeScript
TypeScript Cheat Sheet at a glance


Related: JavaScript Cheat Sheet: Modern Syntax for Browser and Node · JSON Formatter and Validator · Regex Tester for JavaScript.
Reading a lot of our guides? Go ad-free with srvScripts Pro for $6 a month. It also pays for new guides. Cancel any time.