Typescript 是否有一种简洁的函数方式来断言集合中的元素类型?

Typescript 是否有一种简洁的函数方式来断言集合中的元素类型?,typescript,Typescript,假设我们要收集页面上所有复选框的名称 最天真的解决办法是 const names = [...document.querySelectorAll('input[type=checkbox]')] .map(el => el.name); 它没有通过类型检查,因为document.querySelectorAll返回的元素的集合没有名称属性 解决此问题的一种方法是显式指定类型参数document.querySelectorAll 这会让编译器感到高兴,而不是我:现在这段代码不是类型

假设我们要收集页面上所有复选框的名称

最天真的解决办法是

const names = [...document.querySelectorAll('input[type=checkbox]')]
    .map(el => el.name);
它没有通过类型检查,因为
document.querySelectorAll
返回的
元素
的集合没有
名称
属性

解决此问题的一种方法是显式指定类型参数
document.querySelectorAll

这会让编译器感到高兴,而不是我:现在这段代码不是类型安全的,可能会在运行时失败

类型安全的解决方案看起来

const names = [...document.querySelectorAll('input')]
    .filter(el => el.matches('[type=checkbox]'))
    .map(el => el.name);
但它会使代码更加冗长、不那么清晰,而且通常这种解决方案不会扩展(这里我的意思是,您不能一般地应用它,因为不是每个选择器都可以轻松地拆分)

最后,一个同时具有静态和运行时检查的

const names = [...document.querySelectorAll('input[type=checkbox]')]
    .reduce((acc, el) => el instanceof HTMLInputElement ? [...acc, el] : acc, [] as HTMLInputElement[])
    .map(el => el.name);
这是最安全也是最丑陋的


最后,我的问题是:没有办法让它像最新的选项那样安全,但更具可读性吗?

您可以使用带有
过滤器的类型保护来过滤掉不需要的节点并更改数组的类型:

const names = [...document.querySelectorAll('input[type=checkbox]')]
    .filter((el): el is HTMLInputElement => el instanceof HTMLInputElement)
    .map(el => el.name);

丑陋版本所赋予的额外类型安全实际上为您带来了什么?@RobertHarvey这不是“额外”而是“类型安全”。问题中的其他选项不是类型安全的。为什么您不满意
document.querySelectorAll
。你有编译器没有的信息。。。我会用这个version@TitianCernicova-Dragomir现在如果选择器在不更改泛型参数的情况下稍微更改-您可能会在运行时遇到问题(但仍会进行类型检查)。如果查询和类型之间存在不匹配,您的“类型安全”版本也会导致问题。如果选择器返回更多值,但过滤掉一些值,则可能会导致意外行为。。最短的版本可能是使用带有类型保护的
过滤器