我尝试严格地输入Map
,以便它只能包含给定只读数组中的键,我使用以下helper输入该数组:
type ArrayValues<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<infer ArrayValues>
? ArrayValues
: never;
Map正在获取正确的类型,但在数组上循环时,我需要向我为Map提供的ArrayValues
类型添加手动强制转换,这似乎是一种错误的可能性,因为这可能是强制转换实际上不在数组内部的元素,因此它应该给予我一个错误,而不是陷入困境。
function test<Buttons extends ReadonlyArray<string | number>>(
buttonPins: Buttons
) {
const buttonMap = new Map() as Map<ArrayValues<Buttons>, boolean>;
buttonPins.forEach((buttonPin) => {
// This gives error
// Argument of type 'string | number' is not assignable to parameter of type 'ArrayValues<Buttons>'.
// Type 'string' is not assignable to type 'ArrayValues<Buttons>'.
// buttonMap.set(buttonPin, true);
// Using the cast everything works as I want it too
buttonMap.set(buttonPin as ArrayValues<Buttons>, true);
});
return buttonMap;
}
完整的示例代码可以在这里找到:
**问题是:**有没有更好的方法来迭代给定的数组(buttonPins
)以自动修复类型,或者有没有更好的方法来确保我们不会向buttonMap
注入错误的值?
我已经尝试了test
函数的泛型类型的一些不同变体,但是它们都不能帮助我进一步找到解决方案。
2条答案
按热度按时间qojgxg4l1#
你可以这样写(见操场)
1dkrff032#
您的类型
ArrayValues
可以简单地写成以下形式:由于您使用的是带有泛型的条件类型,TypeScript对它的求值很慢,因此
buttonMap.set
的使用是否有效变得模糊。但是,修复方法很简单,使用
Buttons[number]
代替,TypeScript不会延迟计算,所以它允许你在map中设置buttonPin
。Playground
另外,
Map
有两个泛型参数,不需要强制转换为Map<..., ...>
;你可以简单地使用new Map<..., ...>()
,这对于Set
和它们的弱对应物是一样的。