You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>[]'

问题根源

  1. id是虚拟序列化属性,非数据库真实字段:@SerializedPrimaryKey()装饰的id是MikroORM在序列化实体时生成的虚拟属性,并不会存储到MongoDB中。而MikroORM的FilterQuery<T>类型只允许使用实体中映射到数据库真实字段的属性进行查询,TypeScript因此判定id不属于有效查询字段。
  2. 泛型类型推断限制:虽然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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 03:16:06