TypeScript - Generic Interfaces



Generic Interfaces

In TypeScript, the generic interface is similar to the interface but it is defined with one or more type parameters. These type parameters allow the interface to be reused with different data types while still enforcing type safety and consistency.

An interface in TypeScript is a way to define the structure of the object or class. It specifies the expected format which objects or classes should have, allowing to ensure consistency and type safety in the code.

Syntax

You can follow the syntax below to define the generic interfaces.

interface IGeneric<T> {
    value1: T;
    value2: T;
}

In the above syntax, 'IGeneric' is a typed interface, which accepts the custom data type. In the interface, we have used the type 'T' as a value of the value1 and value2 properties.

Example

In the code below, we have created the 'IGeneric' interface with the custom type 'T'. It has value1 and value2 properties of type 'T'.

Next, we have defined the 'obj' object of the IGeneric interface type and used the number data type as a generic type with the interface. After that, we print the value of the 'value1' property of the object in the output.

// Generic interface
interface IGeneric<T> {
    value1: T;
    value2: T;
}

// Object of generic interface
let obj: IGeneric<number> = {
    value1: 10,
    value2: 20
};

console.log(obj.value1);

On compiling, it will generate the following JavaScript code:

// Object of generic interface
let obj = {
    value1: 10,
    value2: 20
};
console.log(obj.value1);

Output

The output of the above example code is as follows –

10

Example

In this code, we use the 'T' and 'U' both data types with the 'IGeneric' interface. The value1 property is of type 'T' and the value2 property is of type 'U' in the interface.

Next, we have defined the 'obj' object of interface type with number and string custom data types.

// Generic interface
interface IGeneric<T, U> {
    value1: T;
    value2: U;
}

// Define object with a generic interface
let obj: IGeneric<number, string> = {
    value1: 10,
    value2: "Hello"
};

console.log(obj.value2);

On compiling, it will generate the following JavaScript code:

// Define object with a generic interface
let obj = {
    value1: 10,
    value2: "Hello"
};
console.log(obj.value2);

Output

The output of the above example code is as follows –

Hello

Example

The below example is very similar to the previous one, but the 'IGeneric' interface contains the merge() method which takes the parameters of type 'U' and returns the value of type 'U'.

While defining the 'obj' object, we used the number and string data types with the interface. It means the merge() method will take two string parameters, and return a string value.

In the output, the code prints the concatenated string, which we have passed as parameters of the merge() method.

// Generic interface
interface IGeneric<T, U> {
    value1: T;
    // method that returns the value of type U
    merge: (a: U, b: U) => U;
}

// Define object with a generic interface
let obj: IGeneric<number, string> = {
    value1: 10,
    merge: (a, b) => a + b
};

console.log(obj.merge("Hello", "world!")); // Hello world!

On compiling, it will generate the following JavaScript code:

// Define object with a generic interface
let obj = {
    value1: 10,
    merge: (a, b) => a + b
};
console.log(obj.merge("Hello", "world!")); // Hello world!

Output

Helloworld!

Generic Interface as a Function Type

Developers can also use the generic interface as a function type. This enables you to use the same function interface across diverse types and scenarios, ensuring type safety without sacrificing flexibility.

Example

In the code below, 'func_interface' accepts the generic types T and U. It defines the structure for the function, which takes the parameter of type 'T' and returns the value of type 'U'.

Next, we have defined the function expression which returns the string length and stored it in the 'stringToLength' variable. The type of the function expression is defined using the generic interface with string and number data types.

Similarly, we have defined another function that converts a number to a string, and its type is func_interface with string and number data type.

Next, we invoke the functions and print their output in the console.

// Define a generic interface for a function
interface func_interface<T, U> {
    (input: T): U;
}

// A specific function that matches the func_interface interface
const stringToLength: func_interface<string, number> = (input) => {
    return input.length;
};

// Using the function
const result = stringToLength("Hello, TypeScript!"); // returns 18
console.log(result);

// Another function that matches the func_interface interface
const numberToString: func_interface<number, string> = (input) => {
    return `Number: ${input}`;
};

// Using the second function
const output = numberToString(123); // returns "Number: 123"
console.log(output);

On compiling, it will generate the following JavaScript code:

// A specific function that matches the func_interface interface
const stringToLength = (input) => {
    return input.length;
};
// Using the function
const result = stringToLength("Hello, TypeScript!"); // returns 18
console.log(result);
// Another function that matches the func_interface interface
const numberToString = (input) => {
    return `Number: ${input}`;
};
// Using the second function
const output = numberToString(123); // returns "Number: 123"
console.log(output);

Output

18
Number: 123

In short, generic interfaces allow developers to reuse the interfaces with multiple data types. Generic interfaces can be used as an object or function type, allowing to reuse the single function or object with different structures.

Advertisements