For*_*eti 13 decorator mixins typescript
在 TypeScript 的装饰器参考页面上,有一段代码被截断,说明如何使用类装饰器覆盖构造函数:
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"));
Run Code Online (Sandbox Code Playgroud)
并在日志中:
class_1 {
property: 'property',
hello: 'override',
newProperty: 'new property' }
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好。但是尝试newProperty
通过点符号访问失败:
类型“Greeter”.ts(2339) 上不存在属性“newProperty”
错误并且未在 VS Code 的提示中列出。可以通过括号表示法访问它,但 TS 警告说
元素隐式具有 'any' 类型,因为类型 'Greeter' 没有索引签名。 ts(7017)
我错过了什么吗?如何以类型安全的方式通过装饰器实现添加新属性?我想像普通的类成员一样拥有普通的编译器支持。
Tit*_*mir 16
设计的装饰器不能改变类的类型。这仍在讨论中,并且在装饰者提案最终确定之前,团队似乎不会改变行为。你可以使用 mixins 来完成这个任务(阅读ts 中的 mixins)
使用 mixins 代码看起来像:
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);
Run Code Online (Sandbox Code Playgroud)
function classDecorator<T extends { new(...args: any[]): {} }>(constructor: T) {
return class extends constructor {
newProperty = "new property";
hello = "override";
}
}
interface classInterface {
newProperty: string;
hello: string;
}
//trick
interface Greeter extends classInterface { };
@classDecorator
class Greeter {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
}
const b = new Greeter();
console.log(b.newProperty);
Run Code Online (Sandbox Code Playgroud)
看来我们可以使用接口技巧来解决这个问题。技巧参考: /sf/answers/3666137611/