我有一个User类,它有一个修饰属性"name".我试图在父类(Base)构造函数中使用Object.assign初始化这个属性,但是值是"undefined".当我移除decorator 时,属性将使用正确的值初始化.参见下面的代码—我使用的是5.4.2版的Typescript .

有人能帮我一下吗?有什么办法能让这个工作吗?

谢谢.

// test.ts
(Symbol as any).metadata ??= Symbol("Symbol.metadata") // Polyfill

function Value(value: string) {
    return (_target: any, context: ClassFieldDecoratorContext) => {
        context.metadata![context.name] = value
    }
}

class Base {
    constructor(data: any) {
        Object.assign(this, data)
    }
}

interface IUser {
    id?: string
    name?: string
}

class User extends Base implements IUser {
    id?: string

    constructor(data: IUser) {
        super(data)
    }

    @Value("test")
    name?: string
}

const data = {
    id: "1",
    name: "John Doe"
}

const user = new User(data)
// user.id is 1
// user.name is undefined

推荐答案

这被认为是TypeScript中的一个bug,在microsoft/TypeScript#56000处报告.

这是因为在现代JavaScript中实现的public class fields在语义上与TypeScrip最初实现它们的方式不同.具体地说,如果在一个JAVASCRIPT子类中声明一个类字段,该字段将被初始化为undefinednot自动从超类继承.如果您希望TypeScrip的行为符合JavaScript,则需要启用the --useDefineForClassField flag.你可能最终会有do个人想这么做,因为事情就是这样发展的.

此外,我们知道decorators与TypeScript最初认为的不同(注意这里的主题吗?)在TypeScript 5.0及以上版本中有一个新的实现.

看起来TypeScript中的downleveling for JavaScriptdecorator 总是像启用了--useDefineForClassField一样.所以,即使你把旗子关了,装饰字段也会突然像旗子开着一样,给你undefined种行为,你在这里看到的.

这是个bug,可能会被修复,但是...最终,如果你正在使用JSdecorator ,你也应该计划使用JS class字段,因为一旦你开始针对实现JSdecorator 的JS运行时,它们也将实现JS class字段.任何用旧字段维护新decorator 的try 可能最终会失败.

Typescript相关问答推荐

类型断言添加到类型而不是替换

无法从Chrome清除还原的初始状态数据

<;T扩展布尔值>;

是否可以从函数类型中创建简化的类型,go 掉参数中任何看起来像回调的内容,而保留其余的内容?

笛卡尔产品类型

创建Angular 为17的动态形状时出错

有没有可能创建一种类型,强制在TypeScrip中返回`tyPeof`语句?

TypeScrip-如何自动推断UNION变量的类型

使用Type脚本更新对象属性

Select 类型的子项

是否可以将类型参数约束为不具有属性?

可以';t使用t正确地索引对象;联合;索引类型

从泛型对象数组构造映射类型

无法使用prisma中的事务更新记录

我可以使用对象属性的名称作为对象中的字符串值吗?

如何在由函数参数推断的记录类型中具有多个对象字段类型

广义泛型类型不加载抽象类型上下文

从平面配置推断嵌套递归类型

Typescript,如何从对象的对象中获取分离的类型

可选字段和联合之间有什么区别吗?