0

I am using "typeorm": "^0.3.7".

import { IRepository, EntityBase } from "core"
import { Database } from "../../db"
import { EntityTarget, Repository } from "typeorm"
export abstract class RepositoryBase<T extends EntityBase> implements IRepository<T> {
    protected _repository: Repository<T>;
    constructor(entity: EntityTarget<T>) {
        this._repository = Database.AppDataSource.getRepository(entity);
    }
    public async GetById (id: number): Promise<T | null> {
        return await this._repository.findOneOrFail({
            where: { id: id },
            relations: ["teachers"]
        });
    }
}

fails:

error TS2322: Type '{ id: number; }' is not assignable to type 'FindOptionsWhere<T> | FindOptionsWhere<T>[] | undefined'.

EntityBase.ts:

import { Entity, PrimaryGeneratedColumn, Column, BaseEntity } from "typeorm"
@Entity()
export abstract class EntityBase extends BaseEntity {
    @PrimaryGeneratedColumn()
    public id: number
    @Column()
    public created: Date
    @Column()
    public modified: Date
    constructor() {
        super();
        this.created = new Date();
    }
}

Student.ts entity:

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
import { EntityBase } from "./EntityBase"
@Entity()
export class Student extends EntityBase {
    @Column()
    public firstName: string

    @Column()
    public lastName: string

    @Column({ unique: true })
    public email: string

    @Column()
    public isSuspended: Boolean

    @ManyToMany((type) => Teacher, (teacher) => teacher.students)
    @JoinTable()
    public teachers: Teacher[]

    constructor(first: string, last: string, email: string, isSuspended?: boolean) {
        super();
        this.firstName = first;
        this.lastName = last;
        this.email = email;
        this.isSuspended = isSuspended ?? false;
    }
}

Using findOneBy({id: id}) in concrete class is OK. Any though on that?

Kok How Teh
  • 3,298
  • 6
  • 47
  • 85

1 Answers1

1

In the StudentRepository we don't need to add the generic type variables in <>. Essentially you want to extend the RepositoryBase with Student type so this will work

export class StudentRepository extends RepositoryBase<Student> {
    constructor() {
        super(Student);
    }

    public override async GetById (id: number): Promise<Student | null> {
        return this._repository.findOneByOrFail({ id });
    }
}

Writing StudentRepository<Student extends EntityBase> makes it generic as well - it's the same as writing T (or anything else) rather than Student.

Hope this solves it for you as well!

PS just a side note: await keyword isn't required when returning from an async function unless it's in a try..catch as explained here