Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript Generics: return instance of class parameter

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?

like image 966
mvermand Avatar asked Jun 14 '18 06:06

mvermand


People also ask

How do you pass a generic class as parameter in TypeScript?

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.

How do I use generic classes in TypeScript?

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> .

How do generics work in TypeScript?

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.

What are some properties of generics in TypeScript?

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.


Video Answer


2 Answers

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;
}
like image 118
Titian Cernicova-Dragomir Avatar answered Jan 01 '23 09:01

Titian Cernicova-Dragomir


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();
}
like image 45
Ed Kolosovsky Avatar answered Jan 01 '23 08:01

Ed Kolosovsky