npm i -D typescriptInstall the compiler as a dev dependency.npx tsc --initScaffold a starter tsconfig.json.npx tsc★Type-check and emit .js beside your .ts.npx tsc --noEmit★Type-check only — no output. Ideal in CI.npx tsc --watchRe-check on save (TS 7 rebuilt this).npx tsx app.tsRun a .ts file directly (tsx / ts-node).// @ts-checkOpt a plain .js file into type-checking.// @ts-expect-errorAssert the next line errors (fails if it doesn't).
let s: string = "hi"★Annotate a variable after its name.let n = 42Inference — n is number, no annotation needed.let ok: booleanstring · number · boolean · bigint · symbol.let a: anyavoidOpts OUT of checking — contagious.let u: unknown★Safe any — must narrow before use.function log(): void {}void = returns nothing useful.const die = (): never => { throw 0 }never = never returns (throws / loops).let id: string | number★Union — one value, several allowed types.
let xs: number[]★Array of numbers (also Array<number>).let ro: readonly string[]Immutable array — no push / splice.let pair: [string, number]Tuple — fixed length & positions.let p: [x: number, y: number]Named tuple elements (labels only).let t: [string, ...number[]]Tuple with a variadic tail.let o: { name: string; age?: number }★Inline object type; age? is optional.let m: { readonly id: number }readonly property — set once.let d: { [key: string]: number }Index signature — arbitrary keys.
type Dir = "n" | "s" | "e" | "w"★Literal union — the idiomatic enum.let x: 0 | 1 | 2Number literal types work too.const t = [1, 2] as const★as const → readonly literal tuple.enum Role { Admin, Editor }emits JSEnum — but it emits runtime code.const enum Flag { On, Off }const enum → inlined, zero output.type In = string | number | nullModel several input shapes in one type.
interface User { id: number; name: string }★Interface — the go-to for object shapes.type Point = { x: number; y: number }★type — names ANY type, not just objects.interface Admin extends User { role: string }Inherit members, then add more.type C = A & BIntersection — must satisfy BOTH.interface Box<T> { value: T }Generic interface — parameterised shape.interface Fn { (u: string): void }Call signature — a callable type.type Id = string // vs interfaceUse type for unions / tuples / mapped types.
if (typeof x === "string") {}★typeof guard — narrows primitives.if (x instanceof Date) {}instanceof — narrows class instances.if ("role" in obj) {}in — narrows by property presence.if (x) { /* truthy */ }Removes null / undefined / 0 / '' from the type.switch (s.kind) { }★Discriminated union — switch on a tag field.function isCat(a: Animal): a is CatType predicate — your own guard.function assert(c: unknown): asserts cAssertion function — narrows after it runs.const _: never = s // exhaustivenever check errors if a case is missed.
function add(a: number, b: number): number★Param types + return type.const f = (x: number): string => `${x}`★Typed arrow function.function g(a: number, b?: number) {}b? optional → number | undefined.function h(a: number, b = 10) {}Default param — type inferred from default.function sum(...ns: number[]): numberRest params typed as an array.function on(e: "click", cb: () => void): voidOverload signatures for varied calls.function each(this: Widget, i: number) {}Typed this parameter (erased at runtime).
function id<T>(x: T): T { return x }★Generic fn — T flows in and out.function first<T>(a: T[]): TT is inferred from the argument.<T extends object>★Constraint — T must fit object.<T, K extends keyof T>K is restricted to T's own keys.function make<T = string>() {}Default type parameter.class Box<T> { constructor(public v: T) {} }Generic class.
class P { x: number = 0 }Field with type + initializer.constructor(public x: number) {}★Parameter property — declares & assigns x.private secret = 1★public · private · protected access.readonly id: numberAssignable only in the constructor.static count = 0Belongs to the class, not instances.abstract class Shape { abstract area(): number }Can't instantiate; subclasses implement.class Dog implements Animal {}★implements — shape-checked at compile time.#real = 42True JS-private field (runtime, not erased).get name(): string { return this._n }Accessors — typed get / set.
@sealed class C {}Class decorator.@log run() {}Method decorator.function log(fn, ctx: ClassMethodDecoratorContext)Standard (TC39) decorator signature.accessor x = 0Auto-accessor field — decoratable.
type K = keyof User★Union of keys: "id" | "name".type T = typeof myConst★Lift a VALUE into its type.type V = User["name"]Indexed access — the type at a key.type E = Arr[number]Element type of an array / tuple type.type Vals = User[keyof User]Union of all property value types.
type Opt<T> = { [K in keyof T]?: T[K] }★Walk every key — here make all optional.{ readonly [K in keyof T]: T[K] }Add readonly to each key.{ -readonly [K in keyof T]-?: T[K] }Strip modifiers with -readonly / -?.{ [K in keyof T as `get${K}`]: T[K] }Key remapping with as (rename keys).type R = { [K in "a" | "b"]: number }Map over a literal union directly.
type NN<T> = T extends null ? never : T★T extends U ? X : Y — a type-level if.type El<T> = T extends (infer U)[] ? U : T★infer captures a type inside the match.type R<F> = F extends () => infer V ? V : neverPull a function's return type out.type Greet = `hello ${string}`Template literal type.type Ev = `on${Capitalize<Key>}`Compose with Uppercase / Capitalize.// `${infer H}${infer T}` on "😀abc"TS 7TS 7: template inference keeps Unicode points.
Partial<T>★All properties optional.Required<T>All properties required.Readonly<T>All properties readonly.Pick<T, K>★Keep only keys K.Omit<T, K>★Drop keys K.Record<K, V>★Object type with keys K, values V.Exclude<U, M> · Extract<U, M>Remove / keep members of a union.NonNullable<T>Remove null and undefined.ReturnType<F> · Parameters<F>A function's return / params tuple.Awaited<T>Unwrap a Promise's resolved type.
el as HTMLInputElement★as — trust me, it's this type (unchecked).value satisfies Config★Check against a type WITHOUT widening it.routes as constFreeze to the narrowest literal type.el!.focus()★Non-null assertion — 'not null here'.let x!: numberDefinite assignment — 'set before use'.x as unknown as TavoidDouble assertion to force unrelated types.
export type { User }★Export a type explicitly.import type { User } from "./u"★Type-only import — erased from JS.declare const VERSION: stringAmbient declaration — 'exists elsewhere'.declare module "*.svg" { const s: string }Type a non-code import.// types.d.tsDeclaration file — types, no implementation.declare global { interface Window {} }Augment global / third-party types.
Promise<string>★Async result type.Array<T> · ReadonlyArray<T>Generic array forms.Map<K, V> · Set<T>Typed collections.() => void★Function type literal.Record<string, number>Quick dictionary type.
"strict": true★TS 7Turns on all strict checks — TS 7 default."noImplicitAny": trueError on inferred any."strictNullChecks": true★null / undefined not in every type."target": "es2024"JS version to emit."module": "esnext"TS 7Module output — TS 7 default."moduleResolution": "bundler"TS 7How imports resolve (node10 gone in 7)."skipLibCheck": trueSkip checking .d.ts files (faster)."paths": { "@/*": ["src/*"] }Import path aliases.