Functions#
TypeScript inherits every JavaScript function form (see
Functions) and adds typed
parameters, typed returns, generic type parameters, overload
signatures, this parameters, and type-narrowing return
forms (x is T, asserts x is T).
Signatures#
A signature is parameters plus a return type.
function add(a: number, b: number): number {
return a + b;
}
const add2 = (a: number, b: number): number => a + b;
type AddFn = (a: number, b: number) => number;
const add3: AddFn = (a, b) => a + b; // params inferred from AddFn
The operator annotates exported signatures; for locals, inference is usually enough.
Optional and default parameters#
? marks a parameter optional (the type includes
undefined); = provides a default and the parameter type
narrows to the non-undefined form.
function greet(name: string = "operator"): string {
return `hello, ${name}`;
}
function listen(host: string, port?: number): void {
// port: number | undefined
}
Optional parameters must come after required ones; for a more flexible API, use an options object.
function fetchJson(url: string, opts: {timeout?: number; signal?: AbortSignal} = {}) {
const {timeout = 5000, signal} = opts;
}
Rest parameters#
...args: T[] collects trailing arguments.
function log(level: "info" | "warn" | "error", ...msg: unknown[]) {
console.error(`[${level}]`, ...msg);
}
Overloads#
Multiple signatures followed by one implementation. The implementation signature is invisible to callers; they see only the overloads.
function len(x: string): number;
function len<T>(x: T[]): number;
function len(x: string | unknown[]): number {
return x.length;
}
len("hi"); // number
len([1, 2, 3]); // number
len(42); // error: no matching overload
Generics#
<T> declares a type parameter. The caller (or inference)
supplies the actual type.
function head<T>(xs: T[]): T | undefined {
return xs[0];
}
const n = head([1, 2, 3]); // n: number | undefined
Constraints with extends.
function pluck<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
pluck({name: "rk", age: 30}, "name"); // string
pluck({name: "rk", age: 30}, "xyz"); // error
Default type parameters.
function load<T = unknown>(): Promise<T> {
// ...
}
Type guards#
A function whose return type is x is T narrows the argument
when called inside a condition.
function isString(x: unknown): x is string {
return typeof x === "string";
}
function isUser(x: unknown): x is User {
return typeof x === "object" && x !== null
&& "id" in x && typeof (x as any).id === "string";
}
if (isString(x)) x.toUpperCase(); // x narrowed to string
Assertion signatures#
asserts returns void but proves the assertion to the
compiler. After the call, the binding is narrowed.
function assert(cond: unknown, msg = "assertion failed"): asserts cond {
if (!cond) throw new Error(msg);
}
function assertString(x: unknown): asserts x is string {
if (typeof x !== "string") throw new TypeError("not a string");
}
function trim(x: unknown): string {
assertString(x);
return x.trim(); // x narrowed to string here
}
this parameter#
A first parameter named this (with a type) tells the
compiler what this must be at the call site. Erased at
runtime.
interface User { name: string; }
function greet(this: User, prefix: string) {
return `${prefix} ${this.name}`;
}
greet.call({name: "rk"}, "hi"); // works
greet("hi"); // error: this is missing
Use this for hand-written callbacks where this
binding matters (jQuery-style callbacks, certain testing
frameworks).
Function-type aliases#
Capture a signature as a reusable type.
type Handler<Req, Res> = (req: Req) => Promise<Res>;
const get: Handler<Request, Response> = async (req) => new Response("ok");
type Predicate<T> = (x: T) => boolean;
const isAdult: Predicate<User> = u => u.age >= 18;
Async functions#
async functions return Promise<T>; the return-type
annotation is the unwrapped type. Awaited<T> strips the
promise wrapper.
async function load(id: string): Promise<User> {
const r = await fetch(`/users/${id}`);
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.json();
}
type LoadedUser = Awaited<ReturnType<typeof load>>; // User
References#
Functions for the runtime function surface.
Types for generics,
Awaited,ReturnType,Parameters.Control flow for narrowing inside conditions.