如何调整Mikro ORM自定义BaseRepository的TS类型解决toJSON报错?
问题
我尝试创建一个包含所有仓库通用自定义方法的BaseRepository,它继承自MikroORM的EntityRepository,但在调用实体的toJSON()方法映射数据时,出现了TypeScript类型错误。
BaseRepository代码如下:
import { AnyEntity, EntityName, EntityRepository, FilterQuery, SqlEntityManager } from '@mikro-orm/core'; export default abstract class BaseRepository<T extends AnyEntity<T>> extends EntityRepository<T> { protected readonly resource: string; protected constructor(_em: SqlEntityManager, entity: EntityName<T>) { super(_em, entity); } async listRecords(query: any, page: number, perPage: number) { try { const [results, count] = await this.findAndCount( <FilterQuery<any>>{}, { limit: perPage, offset: (page - 1) * perPage } ); const mappedData = await Promise.all( results.map(entity => { // 此处触发TypeScript错误 return entity.toJSON(); }) ); return { rows: <EntityDTO<T>[]>mappedData }; } catch (e) { throw e; } } }
错误信息:
TS2339: Property 'toJSON' does not exist on type 'Loaded<T, never>'
自定义仓库示例:
export default class UserRepository extends BaseRepository<User> implements IUserRepository { protected readonly resource = 'users'; constructor(protected readonly _em: SqlEntityManager) { super(_em, User); } async listUsers(query: ListUsersQuery) { const userEntities = await this.listRecords(query.filters, query.page, query.perPage); return new UserCollection(userEntities.rows, userEntities.meta, userEntities.links); // 假设UserCollection类已定义 } }
如何调整BaseRepository的类型定义,消除这个TypeScript错误?
解决方案
方法1:使用MikroORM的wrap工具函数
MikroORM提供的wrap函数可以安全获取实体的操作方法,包括toJSON,同时解决类型推断问题:
- 先导入
wrap:
import { AnyEntity, EntityName, EntityRepository, FilterQuery, SqlEntityManager, wrap } from '@mikro-orm/core';
- 修改映射逻辑(
toJSON是同步方法,无需Promise.all):
const mappedData = results.map(entity => wrap(entity).toJSON());
方法2:显式断言实体类型
直接将Loaded<T, never>类型的实体断言为泛型T,因为Loaded是MikroORM的包装类型,底层实例就是你的实体类:
const mappedData = results.map((entity: T) => entity.toJSON());
方法3:强化泛型约束
在BaseRepository的泛型定义中,明确约束T必须包含toJSON方法,让TypeScript提前确认类型合法性:
interface WithToJSON { toJSON(): any; } export default abstract class BaseRepository<T extends AnyEntity<T> & WithToJSON> extends EntityRepository<T> { // 原有代码保持不变 }
方法4:优化返回值类型断言
返回rows时,替换原有类型断言为更准确的方式,避免类型不安全:
return { rows: mappedData as EntityDTO<T>[] };
内容的提问来源于stack exchange,提问作者z0mbieKale
相关产品推荐
相关产品推荐

