Function behaviour is JavaScript’s. TypeScript adds types for parameters and return values, and ways to describe functions as types (Handbook: More on Functions).
Signatures
FunctionDeclaration:
[async] function [*] Name [TypeParameters] ( Parameters ) [: ReturnType] Block
Parameter:
[Modifiers] BindingName [?] [: Type] [= Expression]
... BindingName [: Type]
ReturnType:
Type | ParameterName is Type | asserts ParameterName [is Type]
A parameter with no annotation and no contextual type is an implicit
any, which is an error under noImplicitAny. A return type left
out is inferred from the return statements; several returns give a
union.
function add(a: number, b: number): number { return a + b; }
const twice: (n: number) => number = n => n * 2; // n is contextually typed
function pick(x: boolean) { return x ? 1 : "a"; } // returns 1 | "a"
A function may destructure a parameter. The annotation describes the whole value:
function f({ a, b = 1 }: { a: string; b?: number }).
Function types
| Form | Meaning |
|---|---|
(a: number) => string | A function type. The parameter name is required |
{ (a: number): string; prop: number } | A call signature, which allows extra properties |
new (a: number) => Date | A constructor type |
{ new (a: number): Date } | A construct signature |
abstract new () => object | Accepts abstract classes too (4.2) |
Function | Any function; calling it returns any. Not recommended |
Optional and default parameters
A parameter with ? may be omitted, and its type includes
undefined. A parameter with a default value is also optional to callers, and
has the type of the default inside the function.
- A required parameter cannot follow an optional one.
- A parameter with a default value can precede a required one, but callers must then
pass
undefinedto use the default. - A parameter cannot have both
?and a default.
function f(a: number, b?: string, c = 1) {}
f(1);
f(1, undefined, undefined);
function g(a = 1, b: string) {}
g("x"); // error: expected 2 arguments
g(undefined, "x"); // fine
function h(a?: number, b: string) {} // error: required after optional
Rest parameters
A rest parameter collects the remaining arguments, and its type is an array or tuple. With a tuple the arguments have their own types. Rest parameters cannot have a default value.
function sum(...values: number[]) {}
function named(...args: [string, number?]) {}
named("a");
named("a", 1);
function capture<T extends unknown[]>(...args: T): T { return args; }
const t = capture("a", 1); // [string, number]
const nums = [1, 2];
Math.atan2(...nums); // error: could be any length
const pair = [1, 2] as const;
Math.atan2(...pair); // fine
this parameters
A parameter named this is a fake first parameter that gives the type of
this inside the function and at each call. It must be listed first, is
erased, and cannot be used on an arrow function, which takes this from its
surroundings.
function age(this: Date) { return this.getFullYear(); }
age.call(new Date()); // fine
age(); // error: wrong this
const bad = (this: Date) => 0; // error
this is checked at the call siteUnder noImplicitThis, using this where its type is unknown is
an error. Under strictBindCallApply, call, apply
and bind check their arguments against the function. A
this type in a class refers
to the current subclass.
Overloads
A function may list several signatures, followed by one implementation. The implementation’s signature is not visible to callers, and must be compatible with each overload.
function format(x: string): string;
function format(x: number): number;
function format(x: string | number) {
return x;
}
format("a"); // string
format(1); // number
format(true); // error
format("a" as string | number); // error: no single overload accepts the union
function only(x: string): void;
function only(x: string, y?: number) {}
only("a", 1); // error: the implementation is not an overload
The signatures must come right before the implementation, with nothing between them. They are erased. Methods and constructors in classes may be overloaded in the same way. A declaration file lists overloads without an implementation.
A union parameter is usually simpler than several overloads, since it also accepts arguments of the union type.
Return types
| Return type | Meaning |
|---|---|
void | No useful value: see special types |
undefined | Returns undefined. Since 5.1 a return is not required |
never | Does not return |
Promise<T> | Required as the type of an async function |
Generator<Y, R, N> | A generator: its yields, its return value and what next takes |
AsyncGenerator<Y, R, N> | An asynchronous generator |
x is T, asserts x | Narrowing signatures |
async function load(): Promise<number> { return 1; }
async function bad(): number { return 1; } // error: must be a Promise
function* count(): Generator<number, string, boolean> {
const next: boolean = yield 1;
return "done";
}
Optional and accessor members
In an object type, a method may be optional, and getter and setter types can be written. Since 5.1 the two types of an accessor pair can be unrelated if both are annotated.
interface Plugin {
setup?(): void;
get version(): string;
set version(value: string);
}
declare const p: Plugin;
p.setup?.(); // needs ?. since it may be missing
p.setup(); // error