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现在如果选择器在不更改泛型参数的情况下稍微更改-您可能会在运行时遇到问题(但仍会进行类型检查)。如果查询和类型之间存在不匹配,您的“类型安全”版本也会导致问题。如果选择器返回更多值,但过滤掉一些值,则可能会导致意外行为。。最短的版本可能是使用带有类型保护的过滤器
。