Generic Type Parameters Make Your Components Reusable Over A Variety Of Types
Topic | Source |
---|---|
๐ฆ TypeScript | TypeScript: Documentation - Generics |
Identity Function: the Hello World of Generics
If you want type safety for a function, where you don't know the specific type that will be used, you can use generics to define the type. A generic is written in <>
and works like a placeholder for the type.
const identity = function <TValue> (value: TValue): TValue {
return value;
};
let x = 23;
const result = identity(x);
export {};
Generics in Classes and Interfaces
You can also use generics in classes and interfaces. To accomplish this, you have to define the class/interface itself with a generic.
interface Stack<TValue> { // you define the generic here
isEmpty: () => boolean;
push: (value: TValue) => void;
top: () => TValue;
pop: () => TValue;
}
class InMemoryStack<TValue> implements Stack<TValue> { //you have to pass the generic through
values: TValue[];
constructor () {
this.values = [];
}
isEmpty (): boolean {
return this.values.length === 0;
}
push (value: TValue): void {
this.values.unshift(value);
}
top (): TValue {
return this.values[0];
}
pop (): TValue {
const topMostValue = this.values.shift()
if (topMostValue === undefined) {
throw new Error('Invalid operation.');
}
return topMostValue;
}
}
const stack = new InMemoryStack<number>(); // here you can define a concrete instance wtih a specific type to create a stack of numbers
stack.push(42);
stack.push(23);
stack.pop();
Generics that Fulfil a Certain Condition
Imagine you have a function using a generic, but you want to call a specific property or function, that the generic has to provide. In this case, you can extend the generic with an interface. In this case, the generic has to provide a name, so we add a HasName
interface that the generic implements.
interface HasName {
name: string;
}
const getName = function <TValue extends HasName> (value: TValue): TValue {
console.log(value.name);
return value;
};
const person1 = {
name: 'Dana K. Scully',
department: 'X-Files'
};
const person2 = {
nickName: 'The smoker',
department: 'CIA'
};
const scully = getName(person1);
export {};