ember.js - Vad är det rätta sättet att skriva en beräknad egenskap med TypeScript och Ember?


Jag har en relativt liten Ember/TypeScript-app som jag har arbetat med i ungefär sex månader. Jag brukade definiera beräknade egenskaper på följande sätt:

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

Men jag har aldrig kunnat få detta att passera TypeScript-kontrollen på ett korrekt sätt. Efter att ha gått igenom Chris Krychos Emberconf-träningsmaterial verkar det som att det "korrekta" sättet att göra detta är som följer:

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

Är detta korrekt? Jag verkar dock sakna något eftersom jag fortfarande får felmeddelanden som detta:

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

Svar #1

För att få dekoratorer att fungera med TypeScript i Ember.js behöver du använda minst ember-decorators 2.0.0 (tillgänglig vid tidpunkten för detta svar som 2.0.0-beta.2) och sätta "experimentalDecorators": true i "compilerOptions"-avsnittet i din tsconfig.json.

Då, för alla versioner av Ember före 3.1 kommer du att skriva computeds så här (som i ditt andra exempel, men utskrivet mer fullständigt för någon annan som snubblar över detta senare). Observera att vi inte behöver returtypen för getter, eftersom den kan härledas korrekt av TypeScript (till skillnad från klassiska Ember computed property callbacks, där returtypen var tvungen att vara explicit).

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')}`
   }
}

Från och med Ember 3.1, som stabiliserar Ember RFC #281, kommer du kunna förenkla detta ytterligare genom att slopa this.get för vilken egenskap som helst som inte involverar Proxies. Observera att du då också kommer kunna slopa this-typdeklarationerna.

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

(Som en parentes: om egenskaperna är kända för att inte vara beräknade egenskaper, utan t.ex. enkla strängar som skickas in i komponenten vid konstruktionstid, kan du göra detta även före Ember 3.1.)


När det gäller eventuella bekymmer om framtiden och stabiliteten för förslaget om dekoratörer: inga föreslagna ändringar i specifikationen kommer att påverka användarna av de dekoratörer vi använder i Ember.js. De kommer att kräva att implementatörer (t.ex. teamet som arbetar med ember-decorators-projektet) gör ändringar, men koden som använder dem (d.v.s. i vanliga appar och tillägg) kommer att förbli opåverkad.

Relaterade artiklar