【问题标题】:Can't use new ecmascript decorators in typescript 2.4.2不能在 typescript 2.4.2 中使用新的 ecmascript 装饰器
【发布时间】:2018-01-22 18:52:22
【问题描述】:

这是我的代码示例:

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 问题建议中的所有内容:

  • 在 tsconfig 中添加 emitDecoratorMetadata 和实验性装饰器
  • 运行 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

【问题讨论】:

  • 你想要的结果是什么?装饰器应该应用于函数/方法,您尝试做的似乎是将方法混合到类中
  • @NickTomlin -- 不正确,装饰器也可以应用于属性。
  • @JohnWeisz 啊,有趣,那我的错!
  • @JohnWeish - 我尝试为方法应用装饰器 - 结果相同。请参阅更新的示例。根据这篇文章medium.com/google-developers/…,我认为按照我的方式添加道具装饰器是可以的

标签: javascript typescript


【解决方案1】:

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

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
                });
            }
        });
    };
}

“外部”get/set 功能只会运行一次,因为在实例上创建属性描述符后,实例属性将对其进行隐藏。

【讨论】:

  • 您的属性装饰器示例确实有效。现在开始使用道具装饰器似乎还为时过早。解决问题我注意到属性装饰器尚不支持的信息(似乎它们存在一些问题),另一方面 babel 也没有使用道具装饰器的示例babeljs.io/docs/plugins/transform-decorators
  • 但是什么应该起作用 - 方法装饰器,在我的打字稿方面不起作用,找不到问题。
  • “现在开始使用 prop 装饰器似乎还为时过早。” -- 我不会这么说,你只需要了解它们的架构限制和所需的解决方法。至于方法装饰器,“不起作用” 是什么意思?运行时什么都没有发生?编译错误?
  • 如问题本身所述,编译错误。您可以使用我的存储库自行查看。
猜你喜欢
  • 2017-06-23
  • 2014-02-14
  • 2018-06-08
  • 2016-10-18
  • 2022-08-15
  • 2017-11-15
  • 2020-04-25
  • 2020-12-07
  • 1970-01-01
相关资源
最近更新 更多