使用 TypeScript 和 Ember 编写计算 属性 的正确方法是什么?

What is the proper way to write a computed property using TypeScript and Ember?

我有一个相对较小的 Ember/TypeScript 应用程序,我已经开发了大约六个月。我曾经按如下方式定义计算属性:

   @computed('styleNamespace', 'status')
   statusClass(componentClassName: string, status: string): string {
     return `${componentClassName}--${status}`
   }

但我一直无法让它正确通过 TypeScript 检查。在查看了 Chris Krycho 的 Emberconf training materials 之后,似乎 "proper" 的方法如下:

   @computed('styleNamespace', 'status')
   get statusClass(this: CertificateCard): string {
     return `${this.get('styleNamespace')}--${this.get('status')}`
   }

这是正确的吗?我似乎遗漏了一些东西,因为我仍然遇到这样的错误:

Error: Assertion Failed: Attempted to apply @computed to statusClass,
but it is not a native accessor function. 
Try converting it to `get statusClass()`

要使装饰器在 Ember.js 中与 TypeScript 一起工作,您至少需要使用 ember-decorators 2.0.0(在回答此问题时可用 2.0.0-beta.2)和在 tsconfig.json.

"compilerOptions" 部分设置 "experimentalDecorators": true

然后,对于 3.1 之前的所有 Ember 版本,您将像这样编写计算(如在您的第二个示例中,但为以后遇到此问题的其他人写得更完整)。请注意,我们不需要 getter 的 return 类型,因为它可以由 TypeScript 正确推断(不像经典的 Ember 计算 属性 回调,其中 return 类型 需要显式)。

import Component from '@ember/component';
import { computed } from '@ember-decorators/object';

export default class TheComponent extends Component {
   styleNamespace: string;
   status: string;

   @computed('styleNamespace', 'status')
   get statusClass() {
     return `${this.get('styleNamespace')}--${this.get('status')}`
   }
}

从 Ember 3.1 开始,稳定了 Ember RFC #281, you'll be able to further simplify this by dropping this.get for any property which does not involve Proxies。请注意,您还可以删除 this 类型声明。

import Component from '@ember/component';
import { computed } from '@ember-decorators/object';

export default class TheComponent extends Component {
  styleNamespace: string;
  status: string;

  @computed('styleNamespace', 'status')
  get statusClass() {
    return `${this.styleNamespace}--${this.status}`;
  }
}

(顺便说一句:如果已知属性不是计算属性,而是例如在构造时传递到组件中的简单字符串,您甚至可以在 Ember 3.1 之前执行此操作。)


关于对装饰器提案的未来和稳定性的任何可能的担忧:对规范的拟议更改不会对我们正在使用的装饰器的消费者产生影响Ember.js。他们将要求实施者(例如从事 ember-decorators 项目的团队)进行更改,但使用代码(即在常规应用程序和插件中)将不受影响。