使用class-transformer转换对象后调用方法报TypeError问题求助
class-transformer嵌套对象转换后实例方法调用报错:TypeError: undefined is not a function
问题场景
使用class-transformer的plainToInstance将JSON反序列化为BasicTime实例后,调用嵌套属性hour的getAs24Hour()或toString()方法时抛出TypeError: undefined is not a function。但直接转换Hour对象时方法调用正常。
相关代码如下:
类定义
export class Hour { hour: number isAm: boolean constructor(hour: number, isAm: boolean) { if (hour < 0 || hour > 11) { throw new Error("Hour should be between 0 and 11 inclusive.") } this.hour = hour this.isAm = isAm } getAs24Hour(): number { return this.isAm ? this.hour : this.hour + 12 } toString(): string { return this.hour < 10 ? `0${this.hour.toString()}` : this.hour.toString() } } export class BasicTime { @Type(() => Hour) hour: Hour; @Type(() => Minute) min: Minute; constructor(hour: Hour, min: Minute) { this.hour = hour this.min = min } }
转换代码
let plain = JSON.parse(jsonString) let time = plainToInstance(BasicTime, plain as BasicTime) time.hour.getAs24Hour() // 报错:函数未定义
问题原因
这是class-transformer的已知问题:当嵌套类拥有带参数的构造函数时,库无法自动正确实例化嵌套对象,导致转换后的hour只是普通JSON对象(POJO),而非Hour类的实例,因此不存在类原型上的方法。
解决方案
方案1:使用@Transform手动实例化嵌套对象
在嵌套属性上添加@Transform装饰器,手动调用类的构造函数完成实例化:
import { Transform, Type } from 'class-transformer'; export class BasicTime { @Type(() => Hour) @Transform(({ value }) => new Hour(value.hour, value.isAm)) hour: Hour; @Type(() => Minute) @Transform(({ value }) => new Minute(value.min)) // 适配Minute类的构造逻辑 min: Minute; constructor(hour: Hour, min: Minute) { this.hour = hour; this.min = min; } }
方案2:给嵌套类添加无参构造函数
修改Hour类,添加无参构造函数供class-transformer自动实例化,同时保留原有带参构造的逻辑:
export class Hour { hour: number; isAm: boolean; constructor(hour?: number, isAm?: boolean) { if (hour !== undefined && isAm !== undefined) { if (hour < 0 || hour > 11) { throw new Error("Hour should be between 0 and 11 inclusive."); } this.hour = hour; this.isAm = isAm; } } getAs24Hour(): number { return this.isAm ? this.hour : this.hour + 12; } toString(): string { return this.hour < 10 ? `0${this.hour.toString()}` : this.hour.toString(); } }
方案3:配置plainToInstance选项(部分版本有效)
在调用plainToInstance时传入enableImplicitConversion选项,允许库自动处理构造函数参数:
let time = plainToInstance(BasicTime, plain as BasicTime, { enableImplicitConversion: true });
注意:该选项的有效性取决于class-transformer的版本,部分旧版本可能不支持此方式处理带参构造的嵌套类。
内容的提问来源于stack exchange,提问作者broun
相关产品推荐
相关产品推荐

