I have a data store and want to create a method to load data from the store. The store contains different types (classes) of data. Let's say my store contains (among other) data of type Author. I want to load author with id 1:
const author1 = store.loadById(Author, 1);
Now how do I have to use generics to get the TS compiler know that author1 is an instance of Author?
I now have
public loadById<T>(entityClass: T, id: number): T {
const entity;
// logic to load the entity ...
return entity;
}
but that is wrong because now the TSC thinks my method returns a entityClass rather than an instance of the entityClass. So how do I have to specify the return type of the method to get author1 to be an instance of Author?
By passing in the type with the <number> code, you are explicitly letting TypeScript know that you want the generic type parameter T of the identity function to be of type number . This will enforce the number type as the argument and the return value.
TypeScript supports generic classes. The generic type parameter is specified in angle brackets after the name of the class. A generic class can have generic fields (member variables) or methods. In the above example, we created a generic class named KeyValuePair with a type variable in the angle brackets <T, U> .
The TypeScript documentation explains Generics as “being able to create a component that can work over a variety of types rather than a single one.” Great! That gives us a basic idea. We are going to use Generics to create some kind of reusable component that can work for a variety of types.
TypeScript Generics is a tool which provides a way to create reusable components. It creates a component that can work with a variety of data types rather than a single data type. It allows users to consume these components and use their own types.
You are passing in the class Author
to the method, not an instance of the Author
class, so the parameter needs to be a constructor signature:
public loadById<T>(entityClass: new () => T, id: number): T {
const entity = new entityClass();
// logic to load the entity ...
return entity;
}
const author1 = store.loadById(Author, 1); // will be of type Author
Or if you have argument to the constructor, you can specify those in the signature:
public loadById<T>(entityClass: new (data: any) => T, id: number): T {
const entity = new entityClass(null as any); // pass data
// logic to load the entity ...
return entity;
}
For those who want to pass a class and return an instance of the class
function newInstance<T extends new () => InstanceType<T>>(TheClass: T): InstanceType<T> {
return new TheClass();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With