Functions That Don't Lie
What does this function even do?
In JavaScript, you've probably seen or written functions like this:
function calculateTotal(items, options) {
// ... what is `items`? An array of numbers? An array of objects?
// ... what is `options`? An object? What are its properties?
// ... what does this function return? A number? A string?
}
To use this function correctly, you have to read its source code, find where it's used elsewhere, or hope there's good documentation. TypeScript eliminates this guesswork by allowing you to type a function's inputs (parameters) and output (return value).
A well-typed function is like a contract. It clearly states what it needs and what it will provide.
Typing Function Parameters
You can add type annotations to function parameters, just like with variables.
function greet(name: string) { ... }
This tells TypeScript that the greet
function must be called with one argument, and that argument must be a string.
Exercise 1: Catching Incorrect Arguments
- The
printUser
function below expects aname
(string) and anage
(number). - Someone has tried to call it with the arguments in the wrong order.
- Hover over the error to see TypeScript explain the problem.
- Fix the function call so that the types of the arguments match the types of the parameters.
Typing Return Values
You can also explicitly type what a function returns. The syntax goes after the parameter list.
function getGreeting(name: string): string { ... }
This function now has a contract: "You must give me a string
, and I promise I will give you a string
back."
Often, TypeScript can infer the return type just by looking at your return
statements. However, being explicit makes your code clearer and ensures the function actually returns what you think it does.
Exercise 2: A Lying Function
- The
calculatePriceWithTax
function says it will return anumber
. - However, inside the function, a bug is causing it to return a formatted string.
- TypeScript spots this lie immediately. Hover over the error on the function declaration to see it.
- Fix the function's logic so that it correctly returns a number.
Click to see the solution
function calculatePriceWithTax(price: number): number {
const tax = price * 0.22;
// ✅ Correct!
return price + tax;
}
Building a Complete, Type-Safe Function
Let's combine everything we've learned: type
aliases, typed arrays, and typed functions. This is the bread and butter of writing type-safe code.
Exercise 3: The User Processor
- We have a
User
type, an array ofusers
, and a functiongetUserNames
. - The function should take an array of
User
objects and return an array of their names (string[]
). - Add the correct type annotations to the function's parameter and its return value.
- Complete the function logic.
Click to see the solution
type User = { id: number; name: string; };
const users: User[] = [{ id: 1, name: "Luigi" }, { id: 2, name: "Mario" }];
function getUserNames(users: User[]): string[] {
return users.map(user => user.name);
}
const userNames = getUserNames(users);
console.log(userNames);
By explicitly typing the inputs and outputs, your function becomes a reliable, self-documenting building block in your application.