An Interface serves as a framework that functions as a contract within our application. It specifies the syntax that classes must adhere to, meaning any class that implements an interface is obligated to provide implementations for all its members. While we cannot create instances of the interface, it can be referenced through the class object that implements it. The TypeScript compiler employs interfaces for type-checking (often referred to as "duck typing" or "structural subtyping") to determine whether an object possesses a particular structure.
The interface solely comprises the declarations of methods and fields, lacking any implementation. It cannot be utilized for constructing anything. A class inherits from the interface, and the class that implements the interface provides definitions for all of its members.
Upon compilation by the Typescript compiler into JavaScript, the interface will be removed from the resulting JavaScript file. Therefore, its function is solely to assist during the development phase.
Interface Declaration
We can declare an interface as below.
interface interface_name {
// variables' declaration
// methods' declaration
}
- An interface is a keyword which is used to declare a TypeScript Interface.
- An interface_name is the name of the interface.
- An interface body contains variables and methods declarations.
Example
interface OS {
name: String;
language: String;
}
let OperatingSystem = (type: OS): void => {
console.log('Android ' + type.name + ' has ' + type.language + ' language.');
};
let Oreo = {name: 'O', language: 'Java'}
OperatingSystem(Oreo);
In the preceding example, an interface named OS has been established, featuring properties for name and language, both of string type. Following this, a function has been defined that takes a single parameter, which corresponds to the OS interface type.
At this point, proceed to compile the TS file into JS, resulting in the output that resembles the following.
Example
let OperatingSystem = (type) => {
console.log('Android ' + type.name + ' has ' + type.language + ' language.');
};
let Oreo = { name: 'O', language: 'Java' };
OperatingSystem(Oreo);
Output:
Android O has Java language.
Use of Interface
We can use the interface for the following things:
- Validating the specific structure of properties
- Objects passed as parameters
- Objects returned from functions.
Interface Inheritance
It is possible to inherit an interface from additional interfaces. In simpler terms, TypeScript permits an interface to extend from zero or more parent types.
The fundamental type may either be a class or an interface. The "extends" keyword can be utilized to establish inheritance between interfaces.
The subsequent example aids in clarifying the concept of interface inheritance.
Syntax
child_interface extends parent interface{
}
Example
interface Person {
name:string
age:number
}
interface Employee extends Person {
gender:string
empCode:number
}
let empObject = <Employee>{};
empObject.name = "Abhishek"
empObject.age = 25
empObject.gender = "Male"
empObject.empCode = 43
console.log("Name: "+empObject.name);
console.log("Employee Code: "+empObject.empCode);
Output:
Name: Abhishek
Employee Code: 43
Consider the preceding example, which aids in comprehending the concept of multiple interface inheritance.
Example
interface Person {
name:string
}
interface PersonDetail {
age:number
gender:string
}
interface Employee extends Person, PersonDetail {
empCode:number
}
let empObject = <Employee>{};
empObject.name = "Abhishek"
empObject.age = 25
empObject.gender = "Male"
empObject.empCode = 43
console.log("Name: "+empObject.name);
console.log("Employee Code: "+empObject.empCode);
Output:
Name: Abhishek
Employee Code: 43
Output:
Array Type Interface
Interfaces can also be utilized to define the array type. The subsequent example assists in clarifying the Array Type Interface.
Example
// Array which return string
interface nameArray {
[index:number]:string
}
// use of the interface
let myNames: nameArray;
myNames = ['Virat', 'Rohit', 'Sachin'];
// Array which return number
interface ageArray {
[index:number]:number
}
var myAges: ageArray;
myAges =[10, 18, 25];
console.log("My age is " +myAges[1]);
In the preceding example, we defined nameArray, which returns a string, and ageArray, which returns a number. The index type for the array is consistently a number, allowing us to access array elements using their respective index positions within the array.
Output:
My age is 18
Interface in a class
TypeScript permits the utilization of interfaces within a class. A class adheres to an interface by employing the implements keyword. This can be illustrated with the following example.
Example
// defining interface for class
interface Person {
firstName: string;
lastName: string;
age: number;
FullName();
GetAge();
}
// implementing the interface
class Employee implements Person {
firstName: string;
lastName: string;
age:number;
FullName() {
return this.firstName + ' ' + this.lastName;
}
GetAge() {
return this.age;
}
constructor(firstN: string, lastN: string, getAge: number) {
this.firstName = firstN;
this.lastName = lastN;
this.age = getAge;
}
}
// using the class that implements interface
let myEmployee = new Employee('Abhishek', 'Mishra', 25);
let fullName = myEmployee.FullName();
let Age = myEmployee.GetAge();
console.log("Name of Person: " +fullName + '\nAge: ' + Age);
In the preceding example, we have defined the Person interface with properties firstName and lastName, as well as methods FullName and GetAge. The Employee class adopts this interface through the use of the implements keyword. Upon implementing an interface, it is essential to specify the properties and methods within the class. Failing to provide these properties and methods will result in a compile-time error. Additionally, we have established a constructor in the class, which requires that we supply the appropriate parameters upon instantiation; otherwise, a compile-time error will occur.
Output:
Name of Person: Abhishek Mishra
Age: 25
Function Types
In TypeScript interfaces, function types can delineate the structure of functions. They enable you to specify the types of parameters as well as the return type of the function. This ensures type-safe assignment of a function to a variable that is typed according to the interface.
Example
interface Add {
(a: number, b: number): number;
}
const sum: Add = (x, y) => {
console.log(`Adding numbers: ${x} + ${y}`);
const result = x + y;
console.log(`Result after addition: ${result}`);
return result;
};
const result = sum(5, 3);
console.log("Sum is", result);
Output:
Adding numbers: 5 + 3
Result after addition: 8
Sum is 8
Explanation:
The Add interface requires a function that accepts two numerical inputs and produces a numerical output. This represents the appropriate type signature for the addition operation.
Optional Properties
Nonetheless, the second line includes an optional attribute from an interface, indicating that you can generate a line such as {name: Alice} or {name: Bob, age: 30}, making it non-mandatory. The ? symbol is utilized to denote these optional fields. This is beneficial when certain values might not always be supplied.
Example
interface User {
name: string;
age?: number;
}
const user1: User = { name: "Alice" };
console.log("User 1 Details:", user1);
const user2: User = { name: "Bob", age: 30 };
console.log("User 2 Details:", user2);
Output:
User 1 Details: { name: 'Alice' }
User 2 Details: { name: 'Bob', age: 30 }
Explanation:
The age attribute is not mandatory. However, user1 can still be considered valid in its absence, while user2 includes both attributes. This flexibility is beneficial for creating adaptable data structures.
Readonly Properties
Readonly properties enable the prevention of property modifications once the object has been instantiated. This restriction is implemented through the readonly keyword. It is beneficial for assigning any constant values that are intended to remain unchanged throughout the application's lifecycle.
Example
interface Car {
readonly brand: string;
model: string;
}
let car: Car = { brand: "Toyota", model: "Corolla" };
console.log("Initial Car Details:", car);
car.brand = "Honda"; // This line will still cause a compile-time error
console.log("Update Car Details:", car);
Output:
error TS2540: Cannot assign to 'brand' because it is a read-only property.
Explanation:
The readonly modifier applied to the brand property indicates that its value cannot be altered once an object is initialized, thereby maintaining the immutability of the properties represented by the brand.
Index Signatures
A method for implementing a dynamic key constraint is by utilizing index signatures, which indicate that an interface can symbolize an object with various flexible keys. To define the type for these keys and their associated values, employ [key: type]: valueType.
Example
interface Scores {
[subject: string]: number;
}
let marks: Scores = {
Math: 95,
Science: 88
};
console.log("Student Scores:", marks);
console.log("Math Score:", marks["Math"]);
console.log("Science Score:", marks["Science"]);
Output:
Student Scores: { Math: 95, Science: 88 }
Math Score: 95
Science Score: 88
Explanation:
The Scores interface can be set up using any string key associated with a numeric value. This is particularly useful, for instance, when dealing with data similar to a dictionary where the keys are not predetermined.
Generic Interfaces
Generic interfaces enable the creation of generic code, facilitating code reuse across various data types. By utilizing a type parameter to outline the interface's structure, you can eliminate the necessity of directly using any. This approach promotes both type safety and the reusability of code.
Example
interface Container<t> {
value: T;
getValue: () => T;
}
const numberContainer: Container<number> = {
value: 42,
getValue: function () {
return this.value;
}
};
console.log("Container Value:", numberContainer.value);
console.log("Retrieved using getValue():", numberContainer.getValue());
</number></t>
Output:
Container Value: 42
Retrieved using getValue(): 42
Explanation:
The parameter T in the Container Interface is designated as a numerical type during its usage. This enables Flexi to function across various data types, including string, boolean, and others.
Difference between interface and inheritance
| SN | Interface | Inheritance |
|---|---|---|
1. |
An Interface is a structure which acts as a contract in our application. It defines the required functions, and the class is responsible for implementing them to meet that contract. | Inheritance is object-oriented programming that allows similar objects to inherit the functionality and data from each other. |
2. |
In an interface, we can only declare properties and methods. | In inheritance, we can use a superclass to declare and define variables and methods. |
3. |
An interface type object cannot declare any new methods or variables. | In this, we can declare and define its own variables and methods of a subclass that inherits a superclass. |
4. |
Interface enforces the variables and methods which have to be present in an object. | A subclass extends the capability of a superclass to suit the "custom" needs. |
5. |
Interfaces are classes that contain body-less structures (abstract or virtual functions). So, we have to derive the interface and then implement all of the functions in the subclass. | Inheritance is the process where one subclass acquires the properties of its superclass. |
6 |
Interfaces support multiple inheritance (a class can implement multiple interfaces). | Inheritance generally supports single inheritance (a class can only extend one class). |
7 |
Interfaces don't have constructors since they don't hold implementation. | Classes in inheritance have constructors to initialize properties. |
FAQs:
- What is an interface in TypeScript?
In TypeScript, an interface serves as a syntactic agreement that an entity must adhere to. It outlines the properties and methods that an object is expected to possess, without providing their implementations.
- Is it possible to utilize interfaces for type validation?
Certainly, interfaces are primarily utilized for type validation. They impose a specific format on classes and objects during the compilation phase.
- What is the difference between an interface and a type in TypeScript?
In TypeScript, both interface and type serve the purpose of outlining the structure of objects. An interface acts as a syntactical agreement, while a type represents a grouping of data types. The interface offers less flexibility compared to the type, which is more adaptable. Although both can articulate object structures, the interface is superior in terms of declaration merging and is typically favored for establishing contracts in object-oriented programming.
- Is it possible for an interface to extend another interface?
Indeed, an interface has the capability to extend one or several interfaces. This feature facilitates structural inheritance and the reuse of code patterns.
- Are interfaces compiled into JavaScript?
No, interfaces exist solely during the phases of development and type-checking. They will not be present in the generated JavaScript code.