TypeScript Generic Classes in Depth
A generic class fixes its type parameter when an instance is created. Its methods can declare further parameters of their own, one per call.
A method with its own type parameter
Store fixes T as number at construction. The map method declares U separately and returns whatever the callback produces.
class Store<T> {
private item: T;
constructor(item: T) {
this.item = item;
}
get(): T {
return this.item;
}
map<U>(fn: (value: T) => U): U {
return fn(this.item);
}
}
const store = new Store<number>(4);
console.log(store.get());
console.log(store.map((n) => 'count: ' + n));A generic method inside a plain class
Picker has no class parameter at all. Its first method declares U per call, so one instance serves string and number arrays.
class Picker {
first<U>(items: U[]): U | undefined {
return items[0];
}
}
const picker = new Picker();
console.log(picker.first(['pen', 'ruler']));
console.log(picker.first([4, 7]));A static member cannot use the class parameter
Static members exist before any instance fixes T, so the parameter has no meaning there. The compiler refuses the declaration.
class Store<T> {
static shared: T;
private item: T;
constructor(item: T) {
this.item = item;
}
}
console.log(Store);Example
class Box<T> {
private value: T;
constructor(value: T) {
this.value = value;
}
get(): T {
return this.value;
}
combine<U>(other: U): [T, U] {
return [this.value, other];
}
}
const box = new Box<string>('pen');
console.log(box.get());
console.log(box.combine(4));Key points
- The class type parameter is chosen once per instance and shared by all its members.
- A generic method declares its own parameter, independent of the class parameter.
- A method parameter can change from call to call on the same instance.
- A generic method can also live inside a plain, non-generic class.
- Static members belong to the class itself, so they cannot use the instance type parameter.
In this example, the box fixes T as string for its whole lifetime, while combine picks U as number for that single call. The returned tuple pairs the class type with the method type.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท TypeScript Playground
Exercise
Why can a static member not use the class type parameter T?