2017-07-27 43 views
1

是否可以在属性装饰器中定义一些属性,并让TS编译器理解这些新属性?TS装饰器:生成编译器可见的属性

在下面的代码中,aExtra属性是通过命名属性访问器v['aExtra']或通过强制转换为任何(<any>a).aFieldExtra访问,但不能直接作为v.aExtra编译器不会看到它(物业不存在)。

有没有可能让编译器看到这个额外的属性?

function withExtra(target: any, fieldName: string) { 
Object.defineProperty(target, fieldName + 'Extra', { 
    get: function(): String { 
     return this[fieldName] + 'Extra'; // <EnumValue[]>this._beanInternalService.getEnumValues(enumType); 
    }, 
    configurable: true, 
    enumerable: true 
    }); 
} 

class A { 
    @withExtra 
    a: string; 
} 

describe('test Extra',() => { 
    it('addsExtra',() => { 
    const v = new A(); 
    v.a = 'a'; 
    expect(v['aExtra']).toEqual('aExtra'); // Works as expected 
    expect((<any>v).aExtra).toEqual('aExtra'); // Compiles, but not very nice 
    // does not compile : 
    // expect(v.aExtra).toEqual('aExtra'); 
    }); 
}); 

回答

2

不,修饰符不会改变TypeScript看到的类的结构。有关于它的issue in GitHub,但这只是一个没有建议的“建议”。即使你有这个,我怀疑你可以自动获得你想要的行为,因为添加的属性名称是动态的。目前no way在类型级别追加字符串文字,所以你甚至不能形容你在做转型:

// without Append<A extends string, B extends string>, you can't type this: 

function appendExtra<T extends string>(originalKey: T): Append<T,'Extra'> { 
    return originalKey+'Extra'; 
} 

我现在想到的最简单的解决方法是只标注这个类在你装饰时手动:

class A { 
    @withExtra 
    a: string; 
    aExtra: string; //added by decorator 
} 

哪个(当然)会被编译器看到。


可以尝试使用混入而不是装饰的,但它会更讨厌,只是为“不好听”为你做的问题铸件。

希望有帮助!祝你好运。

+0

它确实有帮助,即使你的答案表示今天没有“很好”的解决方案。我相信我会手动添加aExtra字段的声明。感谢问题的链接 –