Functions move data around in JavaScript. TypeScript lets you type their inputs and outputs.
Parameter type annotations
Put the type after each parameter:
function greet(name: string) {
console.log("Hello, " + name.toUpperCase() + "!!");
}
Bad arguments are caught:
greet(42);
// Error: Argument of type 'number' is not assignable to parameter of type 'string'.
Even without parameter annotations, TypeScript still checks that you passed the right number of arguments.
Return type annotations
Return types go after the parameter list:
function getFavoriteNumber(): number {
return 26;
}
Often you can omit this : TypeScript infers the return type from return statements. Teams sometimes keep explicit returns for documentation or to lock the API.
Promises
For async functions, wrap the resolved type in Promise<>:
async function getFavoriteNumber(): Promise<number> {
return 26;
}
Contextual typing (anonymous functions)
When TypeScript already knows how a function will be called, it can type the parameters for you:
const names = ["Alice", "Bob", "Eve"];
names.forEach(function (s) {
console.log(s.toUpperCase());
});
names.forEach((s) => {
console.log(s.toUpperCase());
});
s is inferred as string because names is string[] and forEach expects (value: string) => void. That is contextual typing : the surrounding context fills in the type.
Putting it together
function printCoord(x: number, y: number): void {
console.log(`(${x}, ${y})`);
}
function add(a: number, b: number): number {
return a + b;
}
const nums = [1, 2, 3];
const doubled = nums.map((n) => n * 2); // n inferred as number
void means the function does not return a useful value (like console.log).
Practice
- Write
formatUser(name: string, age: number): stringthat returns"Name (age)". - Call it with swapped argument types and read the errors.
- Pass an array of users into
.mapand rely on contextual typing for the callback parameter.