如何修正TypeORM查询中Class constructor CitizenDTO无法调用的错误?
解决TypeORM查询错误:Class constructor CitizenDTO cannot be invoked without 'new'
我来帮你排查这个问题,这个错误本质是TypeORM在尝试实例化你的CitizenDTO类时遇到了障碍,咱们一步步拆解原因和解决方案:
核心问题分析
首先要明确:你给CitizenDTO加了@Entity装饰器,它其实已经是TypeORM的实体类,而不是单纯的数据传输对象(DTO)。当你在from()方法中传入这个类,并调用getMany()时,TypeORM会自动尝试把数据库返回的行数据映射为CitizenDTO的实例,这个过程如果遇到类无法被正常实例化的情况,就会抛出你看到的错误。
常见的触发原因有两种:
- TypeScript编译配置不兼容,导致类构造函数在编译后无法被正确调用
- 混淆了实体类和DTO的职责,导致类结构不符合TypeORM的实例化要求
具体解决方案
方案1:检查并修复TypeScript编译配置
打开你的tsconfig.json,确保以下配置项正确:
{ "compilerOptions": { "target": "ES6", // 至少设为ES6,ES5的类构造函数处理逻辑会导致兼容问题 "experimentalDecorators": true, "emitDecoratorMetadata": true, "module": "commonjs" // 或者其他适合你项目的模块规范,确保装饰器能正常工作 } }
修改后重新编译项目,再执行查询试试。
方案2:明确区分实体类和DTO
既然你用了@Entity装饰器,建议把这个类命名为CitizenEntity(明确它是数据库实体),然后单独定义一个纯DTO类用于数据传输:
// 数据库实体类 @Entity("citizen") export class CitizenEntity { @PrimaryGeneratedColumn() public cit_id: string; @Column() public cit_uid_serial: string; @Column() public cit_last_status_change_date: string; } // 数据传输DTO类 export class CitizenDTO { public cit_id: string; public cit_uid_serial: string; public cit_last_status_change_date: string; }
然后查询时使用实体类,再手动映射到DTO:
const lastProcessedAt = '2019-08-01'; await this.getConnection(); const entities = await this.connection .createQueryBuilder(CitizenEntity, 'citizen') .where('citizen.cit_last_status_change_date >= :date', { date: lastProcessedAt }) .getMany(); // 将实体映射为DTO const citizenDTOs = entities.map(entity => ({ cit_id: entity.cit_id, cit_uid_serial: entity.cit_uid_serial, cit_last_status_change_date: entity.cit_last_status_change_date } as CitizenDTO));
方案3:直接查询原始数据,跳过类实例化
如果不需要TypeORM帮你映射为类实例,也可以用getRawMany()获取原始的JSON对象,这样就不会触发类的实例化过程:
const lastProcessedAt = '2019-08-01'; await this.getConnection(); const results = await this.connection .createQueryBuilder() .select('*') .from('citizen', 'citizen') // 这里直接传表名字符串,不是类 .where('citizen.cit_last_status_change_date >= :date', { date: lastProcessedAt }) .getRawMany();
补充:关于from()方法的第一个参数
TypeORM的from()方法第一个参数支持三种类型:
- 实体类:会自动关联
@Entity装饰器中指定的表名,查询结果会映射为该类的实例 - 表名字符串:直接指定数据库表名,查询结果是原始数据对象
- 子查询对象:可以传入一个
SelectQueryBuilder实例作为子查询
你之前用的是实体类,但因为类的实例化问题触发了错误,调整后就能正常工作了。
内容的提问来源于stack exchange,提问作者just_a_programmer
相关产品推荐
相关产品推荐

