dmunozfer
dmunozfer

Reputation: 590

Generic type with TypeORM repositories

I am trying to make a abstract base service that will be generic type, that type extends from abstract class BaseModel with one property slug.

When i try to do a repository find by the slug attribute I get a typescript error.

this.repository.findOneOrFail({ slug: slug });

Typescript error:

No overload matches this call.
  Overload 1 of 3, '(id?: string | number | Date | ObjectID | undefined, options?: FindOneOptions<Entity> | undefined): Promise<Entity>', gave the following error.
    Argument of type '{ slug: string; }' is not assignable to parameter of type 'string | number | Date | ObjectID | undefined'.
      Object literal may only specify known properties, and 'slug' does not exist in type 'Date | ObjectID'.
  Overload 2 of 3, '(options?: FindOneOptions<Entity> | undefined): Promise<Entity>', gave the following error.
    Argument of type '{ slug: string; }' is not assignable to parameter of type 'FindOneOptions<Entity>'.
      Object literal may only specify known properties, and 'slug' does not exist in type 'FindOneOptions<Entity>'.
  Overload 3 of 3, '(conditions?: FindConditions<Entity> | undefined, options?: FindOneOptions<Entity> | undefined): Promise<Entity>', gave the following error.
    Argument of type '{ slug: string; }' is not assignable to parameter of type 'FindConditions<Entity>'.

Entities:

import { Repository } from 'typeorm';
import {
  Column,
  Entity,
  PrimaryGeneratedColumn,
} from 'typeorm';

export abstract class BaseModel {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  slug: string;
}

@Entity()
export class Link extends BaseModel {
  @Column()
  url: string;
}

BaseService

export abstract class BaseService<Entity extends BaseModel> {
  constructor(protected readonly repository: Repository<Entity>) {}

  async findAll(): Promise<Entity[]> {
    return this.repository.find();
  }

  async findBySlug(slug: string): Promise<Entity> {
    return this.repository.findOneOrFail({ slug: slug });
  }

  async deleteById(id: number): Promise<any> {
    return this.repository.delete(id);
  }
}

Playground

Upvotes: 4

Views: 2315

Answers (1)

dmunozfer
dmunozfer

Reputation: 590

The solution I have found to make it work was:

  async findBySlug(slug: string): Promise<Entity> {
    return this.repository.findOneOrFail({ slug: slug } as any);
  }

I don't know if it's the best way, but it works!

Upvotes: 1

Related Questions