In TypeScript, similar to type aliases (to describe object shapes), interfaces are another way to declare an object shape with an associated name. This tutorial discusses the basics of creating an interface, adding fields and methods, and implementing an interface in another object.
1. Creating an Interface
To create an interface in typescript, we use the interface keyword followed by the interface’s name and then define the interface’s structure using properties and methods. Think of interfaces as blueprints for objects.
Here is the basic syntax:
interface InterfaceName {
// Define properties
propertyName: propertyType;
// Define methods
methodName(): void;
}
For example, the following Account interface represents an account in a financial application. We can add more fields and methods to it.
interface Account {
id: string;
accountNumber: number;
accountHolderName: string;
balance: number;
type: 'Savings' | 'Checking'; // Only one of two values are allowed
readonly openDate: Date; // Readonly Property
closureDate?: Date; // Optional Property
deposit(amount: number): void;
withdraw(amount: number): void;
checkBalance?(): number; // Optional Method
transferFunds(amount: number, recipient: Account): void;
}
2. Adding Members and Methods
Let’s learn to add member fields and methods to the interface that will be available to all the objects that will implement it.
2.1. Specifying Optional Fields
As with object types, interface properties don’t all have to be required in the object. we can indicate an interface’s property is optional by including a '?'
before the ':'
in its type annotation.
interface Account {
id: number;
closureDate?: Date;
//...
};
Now we create objects of Account type with or without the closureDate information.
const acc1: Account = {
id: 10
};
const acc2: Account = {
id: 10,
closureDate: new Date()
};
2.2. Specifying Read-Only Fields
We may sometimes wish to block interface users from reassigning objects’ properties. TypeScript allows adding a ‘readonly’ modifier before a property name to indicate that it cannot be modified once initialized.
interface Account {
id: number;
readonly openDate: Date;
//...
}
We can try to modify a read-only field. The compiler will complain that it cannot be modified.
const acc: Account = {
id: 10,
openDate: new Date()
};
//Error: Cannot assign to 'openDate' because it is a read-only property.
acc.openDate = new Date();
2.3. Creating a Function
Similar to interfaces in other object-oriented languages, typescript allows to definition of a function signature as part of the interface. It is the responsibility of the class (implementing the interface) to implement the function and write the logic in it.
For example, we have added some functions in the interface that an account will generally perform. Here’s how you might implement these additional functions:
interface Account {
// ...
checkBalance(): number;
transferFunds(amount: number, recipient: Account): void;
}
Note that we can declare a function to be optional similar to properties.
interface Account {
checkBalance?(): number;
//...
}
3. Nested Interfaces
Just like object types can be nested as properties of other object types, interface types can also have properties that are themselves interface types (or object types).
For example, we can have two interfaces Account and Address. We can nest the HomeBranch inside in Address interface as follows:
interface Address {
street: string;
city: string;
postalCode: string;
}
interface Account {
//...
address: Address; // Nested interface
}
4. Implementing Interfaces
In TypeScript, we can implement an interface in several ways such as using a class type or using a literal definition. Let’s learn both.
4.1. Class Implementation
In TypeScript, to implement an interface, we must declare a class or object and include all the non-optional properties and methods specified by the interface.
Here’s an example of how to implement an interface in TypeScript. Consider the following Account interface:
interface Account {
id: string;
accountNumber: number;
accountHolderName: string;
balance: number;
type: 'Savings' | 'Checking';
readonly openDate: Date;
closureDate?: Date;
deposit(amount: number): void;
checkBalance?(): number;
}
We can implement this interface to create an object SavingAccount.
class SavingAccount implements Account {
id: string;
accountNumber: number;
accountHolderName: string;
balance: number;
accType: 'Savings';
readonly openDate: Date;
closureDate?: Date;
constructor(id: string, accountNumber: number, accountHolderName: string, balance: number, openedOn: Date, closureDate?: Date) {
this.id = id;
this.accountNumber = accountNumber;
this.accountHolderName = accountHolderName;
this.balance = balance;
this.openDate = openedOn;
this.accType = 'Savings';
this.closureDate = closureDate;
}
deposit(amount: number): void {
this.balance += amount;
console.log(`Deposited ${amount} into account ${this.accountNumber}. New balance: ${this.balance}`);
}
checkBalance(): number {
return this.balance;
}
}
Now we can test that the SavingAccount object works as expected. We can initialize and call its methods:
// Example usage
const accountOpenDate = new Date('2022-01-01');
const savingsAccount = new SavingAccount("1", 123456789, "Alice", 1000, accountOpenDate);
console.log(savingsAccount);
console.log(savingsAccount.checkBalance());
console.log(savingsAccount.deposit(100));
The Output:
[LOG]: SavingAccount: {
"id": "1",
"accountNumber": 123456789,
"accountHolderName": "Alice",
"balance": 1000,
"openDate": "2022-01-01T00:00:00.000Z",
"accType": "Savings",
"closureDate": undefined
}
[LOG]: 1000
[LOG]: "Deposited 100 into account 123456789. New balance: 1100"
4.2. Object Literal Implementation
In object literal implementation, we create an object directly using an object literal notation '{ }'
and ensure that it conforms to a specific interface. This is a way to define the structure of an object inline, without the need for a class.
The following is an inline literal implementation of the Account interface:
const savingsAccount: Account = {
id: '1',
accountNumber: 123456789,
accountHolderName: 'Alice',
balance: 1000,
accType: 'Savings',
openDate: new Date('2022-01-01'),
deposit(amount: number): void {
this.balance += amount;
console.log(`Deposited ${amount} into account ${this.accountNumber}. New balance: ${this.balance}`);
},
checkBalance(): number {
return this.balance;
}
};
//Example Usage
savingsAccount.deposit(500); // Output: Deposited 500 into account 123456789. New balance: 1500
console.log("Current balance:", savingsAccount.checkBalance()); // Output: Current balance: 1500
5. Conclusion
This TypeScript tutorial introduced the concepts of interfaces in TypeScript. We learned to create a simple interface, add fields and methods to it, and finally learned to implement an interface in a class or inline in an object, with examples.
Happy Learning !!
Comments