typescript - 具有可变属性名称的 emberjs glimmer 对象 set()
问题描述
我在 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 like get(this, propertyName)
。
解决方案
您所描述的情况有两个基本问题——一个与 TypeScript 相关,一个与 TypeScript 无关。
TypeScript 的问题是 TS 通常知道属性的名称,并会检查您是否正确设置了内容——无论是在使用普通 JS 属性查找和赋值时,还是在使用 Emberget
和set
函数时。具体来说,Ember 的类型试图确保您在执行get
and时不会出现拼写错误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
(or get
) 的类型只允许任意字符串,那么 TS 在这里根本帮不了你;它会放过它,您必须自己找出错误,而不是编译器提前告诉您有关它的有用信息。
在你遇到的情况下,TypeScript 可能只是看到一个字符串,它说“我没有任何方法可以检查这个字符串是否属于该属性。”</p>
这里有几种改进方法。首先,如果可以的话,你应该弄清楚是否可以将类型限制propertyName
为keyof
它来自的类型。(解释keyof
超出了这个答案的范围,手册中的这一部分和这篇博客文章会让你快速上手。)
其次,与更大的问题有关:您在讨论该问题的另一个答案时指出,问题在于您正试图在单个跟踪的根状态上深入设置属性。一般来说,你不应该以这种方式改变自动跟踪状态——它是旧的观察者驱动模式的遗留物,Ember Classic 使用它的计算属性。相反,更愿意通过该状态的所有者来驱动对该自动跟踪状态的所有更改。然后你根本不需要set
,系统会自动正确更新。
您可以通过自动跟踪嵌套状态本身来做到这一点,或者为它定义一个类,或者使用类似tracked-built-ins之类的东西来包装一个普通的 JS 对象。无论哪种方式,与其从任何地方进入并深度改变该状态,不如仅在拥有该状态的对象上执行。如果您遵循该模式,并将 限制为某个类的位置,那么一切都会“正常工作”——propertyName
无论是在 Ember 端还是在 TypeScript 端。keyof TheOwnerOfTheState
TheOwnerOfTheState
推荐阅读
- angular - 目标入口点“@pebula/ngrid”缺少依赖项:@angular/cdk-experimental/scrolling
- node.js - Post 方法值在节点 js 中返回 null
- java - 基于泛型类型创建新对象
- javascript - 等高列商店页面(图片、标题、价格等)
- odbc - 苹果 M1 上用于 SQL Server 的 ODBC 驱动程序 17
- mysql - 当连接表中不存在相关行时如何显示空列或空列
- django - TemplateSyntaxError at / 第 57 行的块标记无效:'logout_url',预期为 'endif'。您是否忘记注册或加载此标签?
- python-3.x - PyDrive 快速入门和错误 403:access_denied
- reactjs - 如何在 webpack 中使用整个 cacheGroup 作为入口点?
- r - 如何按不同列比较 R 数据框中的两行并对它们执行操作?