- Annotate parameters and return values
- Use optional, default and rest parameters
- Write function types like
(a: number) => numberand understand contextual typing - Know what the
voidandnevertypes mean
A function is a kind of contract: what it accepts and what it returns. In JavaScript this contract lives only in the developer's memory or in comments, and comments quickly go out of date. In TypeScript the contract is written in the function's header, and the compiler checks that it is kept at every call — both when you write the function and when you use it.
Parameters and return values
Each parameter's type is written after its name with a colon. The type of the return value comes after the parentheses. The function below calculates a tip in a restaurant:
function calculateTip(bill: number, percent: number): number {
return (bill * percent) / 100;
}
const tip = calculateTip(40, 15);
console.log(`Tip: ${tip} AZN`);Tip: 6 AZN
The compiler checks both sides of the contract. The caller has to pass all the arguments with the right types, and the function's body has to return the type it promised:
function calculateTip(bill: number, percent: number): number {
return (bill * percent) / 100;
}
calculateTip(40);
function isAdult(age: number): boolean {
if (age >= 18) {
return 'yes';
}
return false;
}tip.ts:5:1 - error TS2554: Expected 2 arguments, but got 1.
5 calculateTip(40);
~~~~~~~~~~~~
tip.ts:1:37
1 function calculateTip(bill: number, percent: number): number {
~~~~~~~~~~~~~~~
An argument for 'percent' was not provided.
tip.ts:9:5 - error TS2322: Type 'string' is not assignable to type 'boolean'.
9 return 'yes';
~~~~~~Optional, default and rest parameters
- An optional parameter has a
?after its name:greeting?: string. Its type is reallystring | undefined, so it may be left out. - A parameter with a default value (
currency = 'AZN') takes its type from that value — herestring. If no argument is passed, the default is used. - A rest parameter (
...numbers: number[]) collects any number of arguments into an array. - Optional parameters must come after the required ones.
function greet(name: string, greeting?: string): string {
return `${greeting ?? 'Hello'}, ${name}!`;
}
function price(amount: number, currency = 'AZN'): string {
return `${amount.toFixed(2)} ${currency}`;
}
function sum(...numbers: number[]): number {
return numbers.reduce((total, n) => total + n, 0);
}
console.log(greet('Murad'));
console.log(greet('Murad', 'Salam'));
console.log(price(12.5), '|', price(12.5, 'USD'));
console.log(sum(1, 2, 3), sum());Hello, Murad! Salam, Murad! 12.50 AZN | 12.50 USD 6 0
?? operator falls back to 'Hello' when greeting is not given.Because an optional parameter may be undefined, TypeScript won't let you use it without a check. In greet we provided a fallback with ??; if we forget to, this happens:
function shout(name: string, greeting?: string): string {
return `${greeting.toUpperCase()}, ${name}!`;
}shout.ts:2:13 - error TS18048: 'greeting' is possibly 'undefined'.
2 return `${greeting.toUpperCase()}, ${name}!`;
~~~~~~~~Function types
In JavaScript, functions are ordinary values: you can store them in variables and pass them to other functions as arguments. So a function has a type too. A function type is written with arrow syntax: (a: number, b: number) => number — “a function that takes two numbers and returns a number”. It is handy to give such a type a name with type.
type Operation = (a: number, b: number) => number;
const add: Operation = (a, b) => a + b;
const multiply: Operation = (a, b) => a * b;
function calculate(x: number, y: number, op: Operation): number {
return op(x, y);
}
console.log(calculate(6, 7, add));
console.log(calculate(6, 7, multiply));
console.log([1, 2, 3].map((n) => n * 10));13 42 [ 10, 20, 30 ]
Notice that in add we didn't write types for a and b, yet there is no error. This is contextual typing: because the function is stored in a variable of type Operation, TypeScript knows the parameters are number. The same goes for map: since the array holds numbers, n automatically becomes a number.
| Type | Meaning | Example |
|---|---|---|
void | the function returns nothing useful | function log(msg: string): void |
never | the function never finishes normally — for example, it always throws | function fail(msg: string): never |
| function type | parameters and return type | (a: number, b: number) => number |
Key points
- Parameter types go after their names; the return type goes after the parentheses.
- The compiler checks the number and types of arguments, and the returned value inside the body.
x?: Tis optional and has the typeT | undefined;x = valueis a default;...xs: T[]is a rest parameter.- A function type uses an arrow:
(a: number, b: number) => number; contextual typing fills in the parameter types. voidmeans nothing is returned;nevermeans the function never finishes normally.
Check yourself
10 questions. Every correct answer earns XP.
(a: number, b: number) => number describe?