A. Laurent
A. Laurent

Reputation: 21

Generics doesn't seem to fit well with QueryFilter

I am trying to set up a base repository class between Mikro-orm and my services, in order to have a simple interface and swap the implementation for another framework if the technology stack requires it. However, the FilterQuery doesn't seem to accept {_id: ObjectId} as an argument:

abstract class MyBaseEntity {
  @PrimaryKey()
  _id: ObjectId;

  @SerializedPrimaryKey()
  id!: string; // won't be saved in the database

  [PrimaryKeyType]: [ObjectId, string]; // i've set this up in the hope it would pick it up in the type check
}


class BaseRepositoryImpl<Entity extends MyBaseEntity> {
  private collection: EntityRepository<Entity>;

  constructor(
    private repository: EntityRepository<Entity>
  ) {
    this.collection = repository;
  }

  async findOne(id: ObjectId): Promise<Entity | null> {
     
    const result = this.collection.findOne({_id: id}); //'{ _id: ObjectId; }' is not assignable to parameter of type 'FilterQuery<Entity>
    // and '_id' does not exist in type '{ [PrimaryKeyType]?: any; }
    return result;
  }
}

Upvotes: 0

Views: 488

Answers (1)

Martin Ad&#225;mek
Martin Ad&#225;mek

Reputation: 18389

There is no need to specify the PK type, objectid/string duality is handled automatically. Also, [PrimaryKeyType]: [ObjectId, string] means "ordered tuple of object id and string, aka composite PK - but those are not supported in mongo at all. You might want to try [PrimaryKeyType]: ObjectId | string instead, but again, should not be needed.

The issue here is TS, using extends in generic type parameter is not enough. Check this snippet to see the fundamental problem:

interface Base {
    id: string;
}

interface Entity extends Base {
    name: string;
}

function fun<T extends Entity>(e: T) {
  e = { id: '1', name: 'n' }; // Type '{ id: string; name: string; }' is not assignable to type 'T'.
}

https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgEJwM4oN4CgCQwAJgFzIZhSgDmA3LgL666iSyIoCi4wYAnsggAPSCCIY0mHARBwAthDIUqIOo2YwAriARhgAexDItIADwAVQSIhiJ3PfwB8ACkXJzASmR5kg5AF5vZGIyAHIARlCAGmRZBTCQUOQGWmQAejT3PgAHFFDsYNJyShpUuLdlUuSk4AkQfTBkTAxgalkAIwAbFDB9ZH5c5FDzUIA6dSA

In other words, this is a TS limitation and you will need to type cast.

Upvotes: 1

Related Questions