Daniel Santos
Daniel Santos

Reputation: 15958

How to initialize a TypeORM Repository based on a Generic Type "T"?

I would like to Initiate a TypeORM Repository based on a Generic Type.

for instance:

import { Connection, Repository } from 'typeorm';

export class GenericService<T> {
    private repository: Repository<T>;

    constructor(connection: Connection) {
        this.repository = connection.getRepository(T);
        // 'T' only refers to a type, but is being used as a value here.ts(2693)
    }

    public async list(): Promise<T[]> {
        return await this.repository.find();
    }

}

But I was not able to pass Generic Type to the ORM Repository Factory.

'T' only refers to a type, but is being used as a value here.ts(2693

How can I create this generic service based on the Generic Type?

PS. I did exactly this with C# and works like a charm. it saves me a lot of time

Upvotes: 7

Views: 9767

Answers (3)

vakhanal1ya
vakhanal1ya

Reputation: 43

2023 Update

(typeorm ^0.3.17, typescript 5.1.3)

According to several issues published in typeorm repository (5152, 9331) almost all previous solutions or it's parts are deprecated (for example, Connection) or even no longer work due to types evolution.

Another approach would be passing Entity itself as generic <T>:

export class GenericService<T extends EntityTarget<ObjectLiteral>> {
    private entityManager: EntityManager;
    private repository: Repository<ObjectLiteral>;

    constructor(entity: T) {
        this.repository = this.entityManager.getRepository(entity);
    }

    public async list() {
        return await this.repository.find();
    }
}

Note that with this sample list() return type would be Promise<ObjectLiteral[]>, not Promise<T[]>.

Upvotes: 1

Usually I useEntityTarget type to avoid this error. The code looks like:

import { Connection, Repository, EntityTarget } from 'typeorm';

export class GenericService<T> {
   private repository: Repository<T>;

   constructor(connection: Connection, repo: EntityTarget<T>) {
      this.repository = connection.getRepository<T>(repo);
   }

   public async list(): Promise<T[]> {
      return await this.repository.find();
   }

}

Upvotes: 5

Yeysides
Yeysides

Reputation: 1292

You can't use types as values in Typescript, so you'll need to use the generic to type check the value instead:

import { Connection, Repository } from 'typeorm';
    
export class GenericService<T> {
   private repository: Repository<T>;
    
   constructor(connection: Connection, repo: T) {
      this.repository: T = connection.getRepository(repo);
   }
    
   public async list(): Promise<T[]> {
      return await this.repository.find();
   }
    
}

Upvotes: 6

Related Questions