泛型似乎不太适合 QueryFilter

问题描述

我正在尝试在 Mikro-orm 和我的服务之间设置一个 base repository 类,以便拥有一个简单的接口并在技术堆栈需要时将实现交换为另一个框架。 但是,FilterQuery 似乎不接受 {_id: ObjectId} 作为参数:

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;
  }
}

解决方法

无需指定PK类型,自动处理objectid/string对偶。另外,[PrimaryKeyType]: [ObjectId,string] 的意思是“对象 id 和字符串的有序元组,也就是复合 PK - 但 mongo 根本不支持这些。您可能想尝试 [PrimaryKeyType]: ObjectId | string,但同样,不应该需要.

这里的问题是 TS,在泛型类型参数中使用 extends 是不够的。检查此代码段以查看根本问题:

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

换句话说,这是一个 TS 限制,您需要进行类型转换。