ember js glimmer set () с именем свойства переменной - PullRequest
1 голос
/ 29 апреля 2020

У меня есть компонент в Ember 3.15, где я пытаюсь сделать что-то вроде

import { action, set } from '@ember/object';

@action
someMethod() {
  const value = ... // something random
  let propertyName = ... // some variable string
  set(this, propertyName, value);
}

Кажется, что он работает нормально в браузере, но машинописный текст помечает строку набора как ошибку (в частности, propertyName аргумент). Так что, если это работает, почему машинописание не нравится?

Это также происходит с get (), где ему не нравятся переменные propertyNames, такие как get(this, propertyName).

Ответы [ 2 ]

2 голосов
/ 08 мая 2020

Существует две основные c проблемы с описанной вами ситуацией - одна из них связана с TypeScript, другая - нет.

Проблема TypeScript заключается в том, что TS знает имена свойств в в общем, и проверит, что вы все настраиваете правильно - как при использовании обычного поиска и присваивания свойства JS, так и при использовании функций get и set Ember. В частности, типы для Ember стараются не допустить опечатки при выполнении get и set. Вы можете понять, почему они не допускают произвольные строки в этом примере:

import Component from '@ember/component';
import { action, set } from '@ember/object';

export default class Whoops extends Component {
  greeting = 'Hello';

  @action updateGreeting(newGreeting) {
    set(this, 'greering', newGreeting);
    //         ----^--- TYPO!!!
  }
}

Если типы для set (или get) просто допускают произвольные строки, TS не сможет вам помочь вообще Вот; он позволил бы ему go, и вам пришлось бы самостоятельно выяснить ошибку - вместо того, чтобы компилятор заранее предупредил вас об этом заранее.

В случае, если вы столкнетесь, предположительно, TypeScript просто видит строку и говорит: «У меня нет никакого способа проверить, принадлежит ли эта строка свойству».

Здесь есть несколько способов улучшить вещи. Прежде всего, если вы можете, вы должны выяснить, возможно ли ограничить тип propertyName, чтобы он был keyof для типа, из которого он исходит. (Объяснение keyof выходит за рамки этого ответа, этот раздел в справочнике и этого сообщения в блоге поможет вам быстрее.)

Во-вторых, хотя и связан с более крупной проблемой: в ходе обсуждения другого ответа на этот вопрос вы отметили, что проблема заключается в том, что вы пытаетесь глубоко установить свойства для одного фрагмента отслеженного состояния root. В общем, вы должны , а не изменять состояние автотрекинга таким образом - это пережиток старых шаблонов, управляемых наблюдателями, которые Ember Classi c использовал с его вычисленными свойствами. Вместо этого предпочитайте направлять все изменения в это состояние с автоматическим отслеживанием через владельца этого состояния. Тогда вам вообще не понадобится set, и система автоматически обновится правильно.

Вы можете сделать это либо путем автоматического отслеживания вложенного состояния , либо путем определения класс для него или с помощью чего-то вроде отслеживаемых встроенных , чтобы обернуть простой JS объект. В любом случае, вместо достижения и глубокого изменения этого состояния из любого места, сделайте это только на объекте, который владеет этим состоянием. Если вы следуете этому шаблону и ограничите propertyName значением keyof TheOwnerOfTheState, где TheOwnerOfTheState - некоторый класс, все будет «просто работать» - как на стороне Ember, так и на стороне TypeScript.

2 голосов
/ 01 мая 2020

Как правило, если ваша собственность @tracked, вам не нужно set, и вы можете просто this[propertyName] = value;.

Однако ваша проблема, вероятно, является общим ограничением машинописи. На самом деле общая проблема набора текста c:

Машинописный текст выполняет только анализ c. Так что он не выполняет ваш код. Поэтому он не может знать, существует ли динамически сгенерированный ключ свойства.

Так что если у вас есть что-то вроде этого:

class Foo {
  data1: number = 1;
  data2: number = 2;
  foo() {
    const fixedProp = 'data1';
    console.log(this[fixedProp]);
    const dynamicProp = 'data' + (1 + 1);
    console.log(this[dynamicProp]);
  }
}

Тогда машинопись не сможет проверить, действительно ли this[dynamicProp] существует, потому что для этого ему нужно выполнить 'data' + (1 + 1);, чтобы он знал, что на самом деле является dynamicProp. Так что невозможно узнать, существует ли this[dynamicProp] с помощью анализа stati c.

Вы можете просто сказать машинописи, что вы хотите, с помощью (this as any)[dynamicProp], и он просто проигнорирует ее , Но, как правило, если вы динамически вычисляете ключи свойств, вы не можете полагаться на stati c analysis.

...