BeCuriouzBeCuriouz

Learn something new every day

🔷 TypeScript
✍️

Giving Your Functions a Type Signature

💡 Annotate a function's parameters and return type to lock down its inputs and output, and use the (arg: T) => R arrow syntax to describe a function's type wherever you need one.

You already know how to annotate variables like let age: number. Functions work the same way — you just annotate the parameters (the inputs) and the return type (the output). Every parameter gets a type after a colon, and the return type goes after the closing parenthesis:

ts
function greet(name: string, times: number): string {
  return name.repeat(times);
}

Here TypeScript checks two things: that every call passes a string and a number, and that the body actually returns a string. If you wrote return times instead, you'd get an error before the code ever runs. You can often omit the return type and let TypeScript infer it from the return statement, but writing it explicitly documents your intent and catches mistakes inside the function.

When a function has no useful return value, its return type is void — for example function log(msg: string): void. And when you need to describe the type of a function itself (say, to type a parameter that receives a callback), you use a function-type expression: (x: number) => number. This arrow syntax reads "takes a number, returns a number":

ts
function applyTwice(f: (x: number) => number, start: number): number {
  return f(f(start));
}

applyTwice(n => n + 1, 10); // 12

Notice that when the callback n => n + 1 is passed in, we don't annotate n — TypeScript already knows from the (x: number) => number signature that n must be a number. This is called contextual typing.

✍️ Giving Your Functions a Type Signature — BeCuriouz