MikroORM自定义仓库使用泛型时遇TS错误的原因问询
问题原因分析
1. 抽象基础实体代码
/* src/common/entities/base.entity.ts */ import { Entity, PrimaryKey, SerializedPrimaryKey, } from '@mikro-orm/core'; import { ObjectId } from '@mikro-orm/mongodb'; @Entity({ abstract: true }) abstract class BaseEntity { @PrimaryKey() _id: ObjectId; @SerializedPrimaryKey() id!: string; } export default BaseEntity;
2. 自定义泛型仓库代码
/* src/models/model.repository.ts */ import { EntityRepository } from '@mikro-orm/mongodb'; import BaseEntity from 'src/common/entities/base.entity'; class ModelRepository<T extends BaseEntity> extends EntityRepository<T> { async get(id: string): T | undefined { const entity = await this.findOne({ id }); return entity; } }
3. 触发的TypeScript错误
Argument of type '{ id: string; }' is not assignable to parameter of type 'FilterQuery<T>'. Object literal may only specify known properties, and 'id' does not exist in type 'FilterQuery<T>[]'
问题根源
id是虚拟序列化属性,非数据库真实字段:@SerializedPrimaryKey()装饰的id是MikroORM在序列化实体时生成的虚拟属性,并不会存储到MongoDB中。而MikroORM的FilterQuery<T>类型只允许使用实体中映射到数据库真实字段的属性进行查询,TypeScript因此判定id不属于有效查询字段。- 泛型类型推断限制:虽然
T继承自BaseEntity,但TypeScript在类型检查时,无法确认所有子类都会保留id属性的查询有效性,再加上findOne的参数支持单个查询对象或查询对象数组的重载,导致类型推断出现混淆,抛出了涉及数组类型的错误提示。
如果要实现按ID查询的功能,正确的做法是使用数据库真实存储的_id字段,并将传入的字符串ID转换为ObjectId:
async get(id: string): Promise<T | undefined> { return this.findOne({ _id: new ObjectId(id) }); }
内容的提问来源于stack exchange,提问作者dangreco
相关产品推荐
相关产品推荐

