使用class-transformer的plainToClass转换嵌套对象报错,求排查
解决class-transformer中@Type装饰器的报错问题
在Node环境中使用class-transformer工具,参考官方文档「处理嵌套对象」示例编写了如下代码:
import { Type, plainToClass } from 'class-transformer'; import 'reflect-metadata'; export class Album { id: number; name: string; @Type(() => Photo) photos: Photo[]; } export class Photo { id: number; filename: string; } const albumJson = { id:12, name:"album", photos:[ { id:01, filename:"photo1.jpg" } ] } let album = plainToClass(Album, albumJson);
运行时出现如下报错:
Unable to resolve signature of property decorator when called as an expression. Argument of type 'undefined' is not assignable to parameter of type 'Object'. @Type(() => Photo)
问题原因
这是类声明的变量提升规则导致的:TypeScript中类声明不会被提升到当前作用域顶部,当Album类中的@Type(() => Photo)执行时,Photo类还未被定义,箭头函数里的Photo此时是undefined,不符合装饰器的参数类型要求,因此触发报错。
解决方案
方案1:调整类的声明顺序
将Photo类的定义移到Album类之前,确保在使用Photo时它已经被声明:
import { Type, plainToClass } from 'class-transformer'; import 'reflect-metadata'; export class Photo { id: number; filename: string; } export class Album { id: number; name: string; @Type(() => Photo) photos: Photo[]; } const albumJson = { id:12, name:"album", photos:[ { id:1, // 注意:原代码的01是八进制数,建议改为十进制1避免歧义 filename:"photo1.jpg" } ] } let album = plainToClass(Album, albumJson);
方案2:使用字符串字面量引用类名
class-transformer支持通过字符串类名来引用尚未声明的类,只需确保字符串与类名完全一致:
import { Type, plainToClass } from 'class-transformer'; import 'reflect-metadata'; export class Album { id: number; name: string; @Type(() => 'Photo') photos: Photo[]; } export class Photo { id: number; filename: string; } const albumJson = { id:12, name:"album", photos:[ { id:1, filename:"photo1.jpg" } ] } let album = plainToClass(Album, albumJson);
额外提示
原代码中id:01的写法需要注意:在严格模式下,以0开头的数字会被解析为八进制数,虽然01是合法的八进制值(对应十进制1),但这种写法容易引发歧义,建议直接使用十进制数字1。
内容的提问来源于stack exchange,提问作者gordie
相关产品推荐
相关产品推荐

