我在Ember 3.15中有一个组件,我尝试在其中执行以下操作
import { action, set } from '@ember/object';
@action
someMethod() {
const value = ... // something random
let propertyName = ... // some variable string
set(this, propertyName, value);
}
它在浏览器中看起来工作正常,但是typescript将set行标记为错误(特别是propertyName参数)。那么,如果它工作正常,为什么typescript不喜欢它呢?
这似乎也发生在get()中,它不喜欢get(this, propertyName)
这样的变量propertyNames。
2条答案
按热度按时间nhhxz33t1#
一般来说,如果你的属性是
@tracked
,你不需要set
,可以只做this[propertyName] = value;
。然而,你的问题可能是一个通用的打字脚本限制。实际上,静态类型的一个通用问题是:
Typescript只做静态分析。所以它不执行你的代码。所以它不能知道一个动态生成的属性键是否真的存在。
所以如果你有这样的东西:
然后typescript将无法验证
this[dynamicProp]
是否实际存在,因为为此它需要 * 执行 *'data' + (1 + 1);
,这样它才能知道dynamicProp
实际是什么。因此,通过静态分析来知道this[dynamicProp]
是否存在是 * 不可能的 *。你可以通过
(this as any)[dynamicProp]
命令typescript做你想做的事情,它会忽略它。但是通常如果你动态计算属性键,你就不能依赖静态分析。camsedfj2#
您所描述的情况有两个基本问题--一个与TypeScript有关,另一个与之无关。
TypeScript的问题是TS通常知道属性的名称,并且会检查您是否正确设置了内容--无论是在使用普通的JS属性查找和赋值时,还是在使用Ember的
get
和set
函数时。Ember的类型试图确保在执行get
和set
时不会出现输入错误。在下面的示例中,您可以看到它们不允许任意字符串的原因:如果类型为
set
(或get
)的只允许任意字符串,TS在这里一点帮助也没有;它会让它过去,您必须自己找出bug-而不是编译器提前告诉您。在您遇到的情况下,TypeScript可能只看到了一个 string,它说“我没有任何方法来检查这个字符串是否属于该属性”。
这里有几种方法可以改进。首先,如果可以的话,您应该弄清楚是否可以将
propertyName
的类型约束为keyof
。(解释keyof
超出了本答案的范围,this section in the handbook和this blog post将帮助您了解最新情况。)第二个问题与更大的问题有关:您在讨论这个问题的另一个答案时注意到,问题在于您试图在单个跟踪的根状态上深入设置属性。一般来说,您 * 不 * 应该以这种方式改变自动跟踪的状态--这是旧的观察者驱动模式的遗留问题,EmberClassic使用它的计算属性。相反,我更喜欢通过状态的 owner 驱动对自动跟踪状态的所有更改。这样你就根本不需要
set
了,系统会自动正确更新。您可以通过自动跟踪嵌套状态 * 本身 * 来实现这一点,也可以为它定义一个类,或者使用类似tracked-built-ins的东西来 Package 一个普通的JS对象。无论哪种方式,都不是从任何地方深入修改该状态,而是 * 只 * 在拥有该状态的对象上进行。如果您遵循这种模式,并将
propertyName
约束为keyof TheOwnerOfTheState
,其中TheOwnerOfTheState
是某个类,则一切都将“正常工作”--无论是在Ember端还是在TypeScript端。