Note: If you're new to TypeScript, check our Getting Started with TypeScript tutorial first.
In TypeScript, an interface is a way to define the shape of an object.
Here's a simple example of an interface. You can read the rest of the tutorial to learn more.
Example
interface Person {
name: string;
age: number;
}
const person: Person = {
name: "Alice",
age: 30,
};
console.log(person);
// Output: { name: 'Alice', age: 30 }
Here, the Person
interface defines that a Person
object should have a name
(string) and an age
(number).
Syntax of TypeScript Interface
An interface is defined using the interface
keyword, followed by the interface name and a set of properties (with types).
interface InterfaceName {
property1: type;
property2: type;
// More properties...
}
Interfaces are just a contract that helps to shape a value; they don't hold actual values themselves.
The actual values are assigned when we create an object based on that interface type. Let's take a look at an example.
Example 1: Car Interface
Let's define an interface named Car
that describes the structure of a car object.
// Define an interface named Car
interface Car {
brand: string;
model: string;
year: number;
}
// Create a Car object
const car: Car = {
brand: "Tesla",
model: "Model 3",
year: 2022,
};
console.log(car);
Output
{ brand: 'Tesla', model: 'Model 3', year: 2022 }
The Car
interface defines the structure of a car object, specifying that it should have brand
, model
, and year
properties.
We then created a car
object of the type Car
, assigning actual values to the brand
, model
, and year
.
Interface with Optional Properties
Some properties in an interface might not always be available. To handle this, TypeScript allows you to define optional properties by adding a ?
after the property name. For example,
interface Car {
brand: string;
model: string;
color?: string; // Optional property
}
let myCar: Car = { brand: "Toyota", model: "Corolla" };
let anotherCar: Car = { brand: "Honda", model: "Civic", color: "Red" };
console.log(myCar);
console.log(anotherCar);
Output
{ brand: 'Toyota', model: 'Corolla' } { brand: 'Honda', model: 'Civic', color: 'Red' }
Here, we've the color
property, which is optional (denoted by ?
), meaning the object can either include or omit it.
The myCar
object doesn't include color
, while the anotherCar
object does.
Frequently Asked Questions
A readonly
property can only be assigned once, typically during object initialization. After that, its value cannot be modified. For example,
// Define a Rectangle interface with read-only properties
interface Rectangle {
readonly width: number;
readonly height: number;
}
// Create a Rectangle object
let myRectangle: Rectangle = { width: 20, height: 30 };
// Error: Cannot assign to 'width' because it is a read-only property
myRectangle.width = 25;
Here, Rectangle
defines width
and height
as readonly
properties. Once the myRectangle
object is created, the values of width
and height
cannot be changed.
Interface for Function Types
You can also use an interface to define the structure of a function, specifying the parameters and return type. For example,
interface Greet {
(name: string): string;
}
const greet: Greet = (name) => `Hello, ${name}!`;
// Call the greet() function and log the result
console.log(greet("Selena"));
Output
Hello, Selena!
Here,
interface Greet { (name: string): string; }
creates a blueprint for a function. It says that the Greet
function should take a name
(a string) as a parameter and return a string
.
Then, we create an actual function greet()
that matches the blueprint:
const greet: Greet = (name) => `Hello, ${name}!`
The greet()
function takes a name
and returns a greeting message (eg, Hello, Selena!
).
Interfaces with TypeScript Classes
In TypeScript, interfaces are also used to define the structure that a class must follow.
Interfaces can specify the properties and methods that a class should have, and the class implements that interface to ensure it follows the required structure.
For example,
// Define an interface for animals
interface Animal {
name: string;
sound: string;
makeSound(): void;
}
// Dog class implements the Animal interface
class Dog implements Animal {
name: string;
sound: string;
constructor(name: string, sound: string) {
this.name = name;
this.sound = sound;
}
makeSound() {
console.log(`${this.name} says: ${this.sound}`);
}
}
// Create a Dog object and call makeSound()
let dog = new Dog("Buddy", "Woof");
dog.makeSound();
// Output: Buddy says: Woof
At first, we defined the Animal
interface, which has:
- the
name
andsound
(bothstring
) properties - the
makeSound()
method that returnsvoid
Then, we defined the Dog
class that implements the Animal
interface. This means the Dog
class must include the name
, sound
properties, and the makeSound()
method, as required by the Animal
interface.
Use Case of Interfaces in Testing
Interfaces are especially useful in testing scenarios. For example, in a payment system, you could define an IPayment
interface outlining the necessary properties and methods.
// Define a payment interface with an amount and a method
interface IPayment {
amount: number;
processPayment(): string;
}
// Implement the IPayment interface in a class
class TestPayment implements IPayment {
amount: number;
constructor(amount: number) {
this.amount = amount;
}
processPayment() {
return `Payment of $${this.amount} processed in test mode.`;
}
}
// Create an instance and call the method
const testPayment = new TestPayment(100);
console.log(testPayment.processPayment());
Output
Payment of $100 processed in test mode.
In testing, the TestPayment
class simulates payment behavior. By implementing the IPayment
interface, it ensures consistency with the real payment class, reducing errors and improving reliability.
This approach guarantees the test class follows the same contract as the production class, ensuring the system works correctly in both real-world and testing scenarios.
Also Read: