Javascript 为什么Array.prototype.includes(searchElement)的参数需要与数组元素相同的类型?
老实说,我不知道我的设置是否有问题,或者这是否是一个打字脚本功能。在以下示例中:Javascript 为什么Array.prototype.includes(searchElement)的参数需要与数组元素相同的类型?,javascript,typescript,Javascript,Typescript,老实说,我不知道我的设置是否有问题,或者这是否是一个打字脚本功能。在以下示例中: type AllowedChars='x'|'y'|'z'; 常量示例arr:AllowedChars[]=['x','y','z']; 功能检查键(e:KeyboardEvent){ 如果(例如arr.includes(e.key)){/如果比较两种不同的类型,那么它们自然是不同的 想象一下你有: type A = {paramA: string}; type B = {paramB: number}; con
type AllowedChars='x'|'y'|'z';
常量示例arr:AllowedChars[]=['x','y','z'];
功能检查键(e:KeyboardEvent){
如果(例如arr.includes(e.key)){/如果比较两种不同的类型,那么它们自然是不同的
想象一下你有:
type A = {paramA: string};
type B = {paramB: number};
const valuesA: A[] = [{paramA: 'whatever'}];
const valueB: B = {paramB: 5};
valuesA.includes(valueB); // This will always be false, so it does not even make sense
在您的情况下,编译器威胁将允许字符
作为与字符串
完全不同的类型。您必须将收到的字符串
强制转换为允许字符
但这是怎么回事,我正在加速用户输入,可能是任何东西
编译器不知道您试图用includes
完成什么。它只知道它们有不同的类型,因此不应该对它们进行比较。是的,从技术上讲,允许数组中的searchElement
参数应该是安全的。includes()
是T
的超类型,但假设它只是T
。在大多数情况下,这是一个很好的假设,因为您通常不想像@GustavoLopes提到的那样比较完全不相关的类型。但您的类型并不是完全不相关的,是吗
有不同的处理方法。您所做的断言可能是最不正确的,因为您断言字符串
是允许的字符
,即使它可能不是。它“完成了任务”,但您对此感到不安是对的
另一种方法是通过本地重写标准库来接受超类型,这有点复杂,并且使用:
但是处理这个问题最简单也是最正确的方法是将exampleArr
的类型扩展到string[]
:
const stringArr: string[] = exampleArr; // no assertion
if (stringArr.includes(e.key)) {} // okay
或者更简洁地说:
if ((exampleArr as string[]).includes(e.key)) {} // okay
加宽到string[]
只是“某种程度上”正确,因为TypeScript为了方便起见不安全地将Array
视为T
中的数组。这对于阅读来说是很好的,但在编写属性时会遇到问题:
(exampleArr as string[]).push("whoopsie"); // uh oh
但是因为你只是从阵列中读取数据,所以它是非常安全的
好的,希望其中一个可以帮助您。祝您好运!通过调用函数.includes()
,您将e.key
有效地分配给参数。您将数组声明为AllowedChars
类型的数组,而e.key
不是该类型。只需使用exampleArr as string[]
?感谢您详尽的回答!这是条件类型的一个非常好的用法。但是,如果您想要缩小范围,它会引发错误,您必须使用此
类型批注。如果您不喜欢被迫强制转换数组以使类型检查器相信您知道自己在做什么,您可以给出一个表示感兴趣的示例在一种机制中,可以更准确地定义这些方法。
if (exampleArr.includes(e.key)) {} // okay
// call to includes inspects as
// (method) Array<AllowedChars>.includes<string>(searchElement: string, fromIndex?: number | undefined): boolean (+1 overload)
if (exampleArr.includes(123)) {} // error
// Argument of type '123' is not assignable to parameter of type 'AllowedChars'.
const stringArr: string[] = exampleArr; // no assertion
if (stringArr.includes(e.key)) {} // okay
if ((exampleArr as string[]).includes(e.key)) {} // okay
(exampleArr as string[]).push("whoopsie"); // uh oh