Functions and Interfaces
In this section, we will cover how to annotate functions and how to use interfaces and classes with TypeScript’s added features.
Typing Functions
In TypeScript, you annotate both the parameters and the return type of a function:
function add(a: number, b: number): number {
return a + b;
}
add(2, 3); // 5
add("2", 3);
// Error: Argument of type 'string' is not assignable
// to parameter of type 'number'
TypeScript can usually infer the return type, so you can omit it:
function add(a: number, b: number) {
return a + b; // TypeScript infers return type: number
}
Arrow functions work the same way:
const multiply = (a: number, b: number): number => a * b;
Optional and Default Parameters
Mark a parameter as optional with ?, or give it a default value:
function greet(name: string, greeting?: string): string {
return `${greeting || "Hello"}, ${name}!`;
}
greet("Ali"); // "Hello, Ali!"
greet("Ali", "Hey"); // "Hey, Ali!"
function greet(name: string, greeting: string = "Hello"): string {
return `${greeting}, ${name}!`;
}
greet("Ali"); // "Hello, Ali!"
The void and never Return Types
Functions that do not return a value have a return type of void:
function logMessage(message: string): void {
console.log(message);
}
The never type is for functions that never return. A function never returns if it always throws an error, or if it runs an infinite loop:
function throwError(message: string): never {
throw new Error(message);
}
Interfaces for Object Shapes
When you need to describe an object structure that you will use in multiple places, define an interface:
interface User {
name: string;
age: number;
email?: string;
}
const ali: User = { name: "Ali", age: 30 };
const bob: User = { name: "Bob", age: 25, email: "bob@example.com" };
Interfaces can describe methods too:
interface User {
name: string;
greet(): string;
}
Interfaces and Classes
If you have read the chapter on object-oriented programming, you know JavaScript classes. TypeScript lets a class implement an interface, which means the class has to have the shape the interface describes:
interface Printable {
print(): void;
}
class Report implements Printable {
constructor(public title: string) {}
print() {
console.log(`Report: ${this.title}`);
}
}
If the class is missing a method or property that the interface requires, TypeScript throws an error at compile time.
Access Modifiers on Class Members
TypeScript adds public, private, and protected access modifiers to class members. JavaScript only recently started supporting private fields with the # prefix:
class BankAccount {
private balance: number;
constructor(
public owner: string,
initialBalance: number,
) {
this.balance = initialBalance;
}
deposit(amount: number): void {
this.balance += amount;
}
getBalance(): number {
return this.balance;
}
}
const account = new BankAccount("Ali", 1000);
account.deposit(500);
console.log(account.getBalance()); // 1500
// account.balance; // Error: Property 'balance' is private
| Modifier | Accessible From |
|---|---|
public |
Anywhere (this is the default) |
private |
Only within the class |
protected |
Within the class and its subclasses |