TypeScript Interface Example: How to Create and Implement?

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

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.