【问题标题】:Getting ID of clicked element using strict type使用严格类型获取点击元素的 ID
【发布时间】:2022-10-05 21:14:26
【问题描述】:

假设我们要使用以下 TypeScript 代码记录单击元素的 ID 属性:

onClick(event) {
  console.log(event.target.attributes.id.nodeValue);
}

上面的函数接收点击的对象作为参数,但是本例中的类型是any。如果我检查typeof event 的结果,我会得到object。所以我会修改我的代码如下:

onClick(event: object) {
  console.log(event.target.attributes.id.nodeValue);
}

在这种情况下,我在 VS Code 中收到如下错误:

那么这是怎么回事呢?使用类型 any 作为参数类型有效,控制台记录所需的 ID 没有任何错误,但如果我决定使用严格的 object 作为参数类型,我的代码不会编译。问题出在哪里?

受影响的 HTML 代码如下;

<h1 id=\"foo\" (click)=\"onClick($event)\">...</h1>
  • @T.J.Crowder 谢谢,我在帖子末尾添加了一个 HTML 示例。

标签: javascript jquery angular typescript


【解决方案1】:

如果我检查typeof event 的结果,我会得到object

那是运行时代码,所以它是 JavaScript typeof 运算符,表示 "object" for全部对象(和null)。

所以我会修改我的代码如下......我收到一个错误是 VS Code,如下所示

普通对象没有 target 属性。

click 事件的事件对象的类型是 MouseEvent。 (您已标记。如果您使用jQuery 或DOM 附加事件,它将是DOM 的MouseEvent。如果您使用Angular 附加事件,@987654324 @ 它也将是 DOM 的 MouseEvent。警告:我不使用 Angular。)您可能还想要 event.currentTarget.idevent.target.id 而不是使用 attributes 集合和 nodeValue,因为id 属性是一个反射属性。

,DOM 的MouseEvent 接口从Event 继承其currentTarget 属性,它只是将其定义为EventTarget。你知道这将是一个Element,但不幸的是界面只是说它是EventTarget。 (target 也是如此。)

据我所知,MouseEvent 没有预定义的接口,将currentTarget 定义为Element。您可以可靠地(在这种情况下)使用类型断言:

onClick(event: MouseEvent) {
    console.log((event.target as Element).id); // Or `(event.currentTarget as Element).id`
}

Playground link

我不喜欢类型断言,但它们有时是必要的。

有时你会看到人们做同样的断言略有不同,就像这样:

onClick({target}: {target: Element}) {
    console.log(target.id);
}
// or
onClick({currentTarget}: {currentTarget: Element}) {
    console.log(currentTarget.id);
}

Playground link

您可以创建一个可重用的类型,如下所示:

interface ElementMouseEvent extends MouseEvent {
    currentTarget: Element;
    target: Element;
}

...然后使用它(它仍然是一个断言,但同样是一个安全的断言):

onClick(event: ElementMouseEvent) {
    console.log(event.target.id); // Or `event.currentTarget.id`
}

Playground link

如果你想去完全typesafe,你可以有一个类型断言函数,如果断言无效,它会抛出一个明确的运行时错误:

function assertIsElement(obj: object | null): asserts obj is Element {
    if (!(obj instanceof Element)) {
        throw new Error(`Object is not an Element instance`);
    }
}
// ...
onClick({currentTarget}: MouseEvent) {
    assertIsElement(currentTarget);
    console.log(currentTarget.id);
}

Playground link

如果你控制onClick 的使用位置(例如,你知道你在Element 上使用它),那可能是矫枉过正。

【讨论】:

  • 如果我将类型更改为MouseEventevent.currentTarget.id 返回两个错误。第一的,对象可能是“空”.ts(2531), 第二,类型 'EventTarget'.ts(2339) 上不存在属性 'id'.我正在使用基于 TypeScript 的 jQuery 和 Angular,所以这是一件复杂的事情。
  • @Viktor - 我忘记了 DOM 事件对象仅将目标定义为 EventTarget,而不是 Element(因为它们也以 Document 为目标)。我习惯了通用的 React 合成事件类型 (MouseEvent&lt;Element&gt;)。我已经更新了答案。
  • 感谢您的解释,我仍然不明白为什么没有正确的方法来获得一个身份......我可能太无知了。 xD
  • @MMatthieu - 上面的大多数选项都是“正确的”。我刚刚添加了一个完全类型安全的,但在大多数情况下,这将是矫枉过正。
猜你喜欢
  • 1970-01-01
  • 2016-06-30
  • 1970-01-01
  • 2011-12-11
  • 1970-01-01
  • 1970-01-01
  • 2012-04-12
  • 2022-07-19
  • 2019-01-11
相关资源
最近更新 更多