通过TypeScript中的装饰器向类添加属性

通过TypeScript中的装饰器向类添加属性,typescript,decorator,mixins,Typescript,Decorator,Mixins,在TypeScript的Decorator参考页上,有一段代码被截取,说明了如何用类Decorator重写构造函数: function classDecorator<T extends {new(...args:any[]):{}}>(constructor:T) { return class extends constructor { newProperty = "new property"; hello = "override";

在TypeScript的Decorator参考页上,有一段代码被截取,说明了如何用类Decorator重写构造函数:

function classDecorator<T extends {new(...args:any[]):{}}>(constructor:T) {
    return class extends constructor {
        newProperty = "new property";
        hello = "override";
    }
}

@classDecorator
class Greeter {
    property = "property";
    hello: string;
    constructor(m: string) {
        this.hello = m;
    }
}

console.log(new Greeter("world"));
到目前为止还不错。但是尝试通过点符号访问
newProperty
失败,原因是:

属性“newProperty”在类型“Greeter”上不存在。ts(2339)

错误,并且未在VS代码的提示中列出。可以通过括号表示法访问它,但TS警告

元素隐式具有“any”类型,因为类型“Greeter”没有索引签名。ts(7017)


我错过什么了吗?如何以类型安全的方式通过装饰器实现添加新属性?我希望像普通类成员一样获得普通编译器支持。

设计的装饰器无法更改类的类型。这仍在讨论中,在装饰师提案最终确定之前,似乎不会改变行为。您可以将mixin用于此任务(阅读)

使用mixin时,代码看起来像:

function classDecorator<T extends { new(...args: any[]): {} }>(constructor: T) {
    return class extends constructor {
        newProperty = "new property";
        hello = "override";
    }
}

const Greeter = classDecorator(class {
    property = "property";
    hello: string;
    constructor(m: string) {
        this.hello = m;
    }
});
type Greeter = InstanceType<typeof Greeter> // have the instance type just as if we were to declare a class

console.log(new Greeter("world").newProperty);
函数类装饰器(构造函数:T){
返回类扩展了构造函数{
newProperty=“新属性”;
hello=“覆盖”;
}
}
const Greeter=classDecorator(类{
property=“property”;
你好:字符串;
构造函数(m:string){
this.hello=m;
}
});
type Greeter=InstanceType//将实例类型与声明类一样
console.log(新问候者(“世界”).newProperty);
函数类装饰器(构造函数:T){
返回类扩展了构造函数{
newProperty=“新属性”;
hello=“覆盖”;
}
}
接口类接口{
newProperty:字符串;
你好:字符串;
}
//诡计
接口接线员扩展classInterface{};
@阶级装饰家
迎宾员{
property=“property”;
你好:字符串;
构造函数(m:string){
this.hello=m;
}
}
常数b=新的迎宾员();
console.log(b.newProperty);
看来我们可以用界面技巧来解决这个问题。 技巧参考:

为什么是“按设计”?似乎decorators是将mixin引入类的完美方式。我可以查找GitHub问题,它只是没有实现以允许这样做,这是一个深思熟虑的决定。@Forseti这是一个围绕它的开放问题,讨论很长,但这条评论似乎相关:,因此,更多的是一种尚未实现的问题,这破坏了我们首先使用decorator的原因。使用decorator的目的是不必扩展类。如果没有,我们可以扩展到实现这些新属性的类,并在Greter..@JaviMarzán的构造函数中调用
super()
,这是当前唯一的选项,因为不允许类装饰器突变。请参阅以下Github问题:在评论中也可以找到blackmiaool的诀窍。
function classDecorator<T extends { new(...args: any[]): {} }>(constructor: T) {
    return class extends constructor {
        newProperty = "new property";
        hello = "override";
    }
}

const Greeter = classDecorator(class {
    property = "property";
    hello: string;
    constructor(m: string) {
        this.hello = m;
    }
});
type Greeter = InstanceType<typeof Greeter> // have the instance type just as if we were to declare a class

console.log(new Greeter("world").newProperty);