不能在typescript 2.4.2中使用新的ecmascript装饰器

时间:2017-08-14 20:54:05

标签: javascript typescript

这是我的代码示例:

function enumerable(value: boolean) {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    descriptor.enumerable = value;
  };
}

class A {
  @enumerable(false)
  a: number = 1
  b: number = 2

  myMethod () {}
}

const a = new A()

无论我尝试什么,我都会得到:

D:(real path removed)/first-try-typescript>tsc --emitDecoratorMetadata --experimentalDecorators decorators.ts
decorators.ts(8,3): error TS1240: Unable to resolve signature of property decorator when called as an expression.

我已尝试过来自相同stackoferflow问题建议的所有内容:

  • 添加emitDecoratorMetadata& experimentalDecorators to tsconfig
  • 运行tsc --emitDecoratorMetadata --experimentalDecorators
  • :any添加到标记装饰器函数返回值
  • 添加descriptor: TypedPropertyDescriptor<any>类型

我总是得到这个错误。在终端和Webstorm代码提示中都有。方法装饰器 - 同样的事情(见下面的例子)。

function test(target: Object,
              propertyKey: string,
              descriptor: TypedPropertyDescriptor<any>): any {
  return descriptor;
}

class A {
  a: number = 1
  b: number = 2

  @test
  myMethod () {}
}

const a = new A()

最新代码在此处 - https://github.com/rantiev/first-try-typescript

1 个答案:

答案 0 :(得分:0)

不幸的是,属性装饰器无权访问属性描述符,因为属性存在于类实例上,而装饰器在任何实例可能存在之前被评估。此外,您只能对属性装饰器使用以下签名:

function (target: any, propKey: string | symbol)

这里没有描述符。

你也不能只做Object.defineProperty(target, propKey.toString, { enumerable: false, value: ... }),因为它会在你班级的所有实例中共享,即在一个实例中设置属性会泄漏到另一个实例中。

虽然可以实现你正在做的事情,但有点复杂。我通常做的是在原型上创建一个getter,它会及时创建所需的属性描述符。类似的东西:

function enumerable(value: boolean) {
    return function (target: any, propKey: string | symbol) {
        Object.defineProperty(target, propKey, {
            get: function () {
                // In here, 'this' will refer to the class instance.
                Object.defineProperty(this, propKey.toString(), {
                    value: undefined,
                    enumerable: value
                });
            },
            set: function (setValue: any) {
                // In here, 'this' will refer to the class instance.
                Object.defineProperty(this, propKey.toString(), {
                    value: setValue,
                    enumerable: value
                });
            }
        });
    };
}

“外部”获取/设置功能将只运行一次,因为实例属性将在实例上创建属性描述符后将其隐藏。