ES5与experimentalDecorators配置下,Accessor Decorators descriptor为undefined
TypeScript访问器装饰器descriptor始终为undefined的解决办法
问题场景
你定义了Point类和configurable装饰器,tsconfig里target设为ES5、开启了experimentalDecorators,但运行时装饰器中的descriptor参数一直是undefined,代码和配置如下:
代码示例
class Point { private _x: number; constructor(x: number, y: number) { this._x = x; } @configurable(false) get x() { return this._x; } } function configurable(value: boolean) { return function (target: any, propertyKey: string, descriptor?: PropertyDescriptor) { console.log("called.....", descriptor); if (descriptor) { console.log("called.....", descriptor); descriptor.configurable = value; } }; }
tsconfig配置
{ "compilerOptions": { "target": "ES5", "experimentalDecorators": true } }
问题原因
当TypeScript编译目标设为ES5时,类的访问器(getter/setter)会被编译成基于Object.defineProperty的ES5兼容代码,但实验性装饰器在ES5模式下,不会为访问器装饰器传入descriptor参数。这是因为ES5本身没有原生类语法,TypeScript的模拟实现无法在装饰器阶段直接提供完整的PropertyDescriptor。
解决方案
方案1:升级编译目标到ES6+
修改tsconfig的target为ES2015(即ES6)或更高版本,此时TypeScript会使用原生类语法编译,访问器装饰器就能正确获取到descriptor:
{ "compilerOptions": { "target": "ES2015", "experimentalDecorators": true } }
方案2:手动获取并修改descriptor(兼容ES5)
如果必须保持ES5编译目标,可以在装饰器中手动从类原型上获取访问器的描述符,修改后重新定义:
function configurable(value: boolean) { return function (target: any, propertyKey: string) { // 从类原型上获取访问器的descriptor const descriptor = Object.getOwnPropertyDescriptor(target, propertyKey); if (descriptor) { descriptor.configurable = value; // 重新定义访问器 Object.defineProperty(target, propertyKey, descriptor); } }; }
注:这里的target指向类的原型,你的get x是定义在类原型上的访问器,因此该方法可以正常生效。
验证
修改后运行代码,装饰器中的descriptor将不再是undefined,configurable属性会被正确设置。
内容的提问来源于stack exchange,提问作者Nilesh Chavan
相关产品推荐
相关产品推荐

