TypeScript - Generic Interface
Here, you will learn about the generic interface in TypeScript.
The generic type can also be used with the interface. The following is a generic interface.
interface IProcessor<T>
{
result:T;
process(a: T, b: T) => T;
}
The above IProcessor
is a generic interface because we used type variable <T>
. The IProcessor
interface includes the generic field result
and the generic method process()
that accepts two generic type parameters and returns a generic type.
As you learned, you can use interface as type. In the same way, generic interface can be used as type, as shown below.
interface KeyPair<T, U> {
key: T;
value: U;
}
let kv1: KeyPair<number, string> = { key:1, value:"Steve" }; // OK
let kv2: KeyPair<number, number> = { key:1, value:12345 }; // OK
As you can see in the above example, by using generic interface as type, we can specify the data type of key and value.
In the same way, as you learned, you can use interface as function type. Generic interface can also be used as the function type.
interface KeyValueProcessor<T, U>
{
(key: T, val: U): void;
};
function processNumKeyPairs(key:number, value:number):void {
console.log('processNumKeyPairs: key = ' + key + ', value = ' + value)
}
function processStringKeyPairs(key: number, value:string):void {
console.log('processStringKeyPairs: key = '+ key + ', value = ' + value)
}
let numKVProcessor: KeyValueProcessor<number, number> = processNumKeyPairs;
numKVProcessor(1, 12345); //Output: processNumKeyPairs: key = 1, value = 12345
let strKVProcessor: KeyValueProcessor<number, string> = processStringKeyPairs;
strKVProcessor(1, "Bill"); //Output: processStringKeyPairs: key = 1, value = Bill
In the above example, generic interface KeyValueProcessor
includes the generic signature of a method without the method name. This will allow us to use any function with the matching signature. The generic type will be set at the time of creating a variable such as numKVProcessor
and strKVProcessor
.
The above example can be re-written as below.
interface KeyValueProcessor<T, U>
{
(key: T, val: U): void;
};
function processKeyPairs<T, U>(key:T, value:U):void {
console.log(`processKeyPairs: key = ${key}, value = ${value}`)
}
let numKVProcessor: KeyValueProcessor<number, number> = processKeyPairs;
numKVProcessor(1, 12345); //Output: processKeyPairs: key = 1, value = 12345
let strKVProcessor: KeyValueProcessor<number, string> = processKeyPairs;
strKVProcessor(1, "Bill"); //Output: processKeyPairs: key = 1, value = Bill
As you can see, we declared a function type numKVProcessor
as let numKVProcessor: KeyValueProcessor<number, number> = processKeyPairs;
. The type number will be used as the underlaying type of generic functionprocessKeyPairs
. This will remove the need of defining separate functions for different data types.
The generic interface can also be implemented in the class, same as the non-generic interface, as shown below.
interface IKeyValueProcessor<T, U>
{
process(key: T, val: U): void;
};
class kvProcessor implements IKeyValueProcessor<number, string>
{
process(key:number, val:string):void {
console.log(`Key = ${key}, val = ${val}`);
}
}
let proc: IKeyValueProcessor<number, string> = new kvProcessor();
proc.process(1, 'Bill'); //Output: processKeyPairs: key = 1, value = Bill
In the above example, the generic type parameters are being set at the time of implementing an interface e.g class kvProcessor implements IKeyValueProcessor<number, string>
. This will force us to implement the method process()
with number and string parameters.
We can also make the class kvProcessor
as generic. Let's see how to create a generic class.