gpt4 book ai didi

arrays - 为什么我可以调用 array.some() 而不是 array.every() 联合数组类型?

转载 作者:行者123 更新时间:2023-12-05 01:49:11 31 4
gpt4 key购买 nike

所以,假设我有一个像这样的(愚蠢的)函数:

function doSomething(input: number|string): boolean {
if (input === 42 || input === '42') {
return true;
} else {
return false;
}
}

为什么我可以调用 array.some()像这样:

function doSomethingWithArray(input: number[]|string[]): boolean {
return input.some(i => doSomething(i));
}

但不是array.every()像这样:

function doEverythingWithArray(input: number[]|string[]): boolean {
return input.every(i => doSomething(i));
}

这给了我这个错误:

This expression is not callable.Each member of the union type '{ (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; } | { ...; }' has signatures, but none of those signatures are compatible with each other.

我不明白其中的区别。在我看来,两者都应该起作用,或者两者都不起作用。我错过了什么?

请注意 doSomething()接受 number|string作为它的论点,所以它应该与 number[]|array[] 的每个元素一起工作,就像它对 array.some() 所做的一样,不应该吗?

最佳答案

这本质上是 TypeScript 的当前限制;见microsoft/TypeScript#44373 .


TypeScript 长期以来一直无法在 union 上调用方法数组类型。最初您根本无法调用函数联合,因为编译器不知道如何将多个签名合并为一个可用的签名。参见 microsoft/TypeScript#7294 :

// Before TS3.3:
declare const arr: string[] | number[];
arr.some(() => true); // error
arr.map(() => 1); // error
arr.every(() => true); // error

引入 TypeScript 3.3 some supportmicrosoft/TypeScript#29011 做到这一点, 通过接受 intersection来自联合成员的参数。

但是这种支持只是针对相对简单的情况添加的,其中最多一个工会成员是 generic函数,最多一个工会成员是overloaded功能。因此,如果您要合并的数组方法是通用的或重载的,您仍然无法调用它们。所以有一个改进,但一些方法如 map() 仍然不可调用。参见 microsoft/TypeScript#36390 :

// TS3.3
declare const arr: string[] | number[];
arr.some(() => true); // okay
arr.map(() => 1); // error
arr.every(() => true); // okay

在某些时候,决定向 every() 添加一个通用重载,以便它可以充当 type guard function。 ;见microsoft/TypeScript#38200 .这很有用,但不幸的是,这意味着 every() 也停止处理数组类型的联合。这是随 TypeScript 4.0 一起发布的:

// TS 4.0
declare const arr: string[] | number[];
arr.some(() => true); // okay
arr.map(() => 1); // error
arr.every(() => true); // error

对于 TypeScript 4.2 microsoft/TypeScript#31023被合并,这增加了对泛型调用签名的调用联合的一些支持,只要泛型类型参数是相同的。但是对于重载的调用签名,问题仍然存在:

// TS 4.2+
declare const arr: string[] | number[];
arr.some(() => true); // okay
arr.map(() => 1); // okay
arr.every(() => true); // error

这就是我们目前所处的位置。


也许在某个时候,microsoft/TypeScript#44373 会得到解决。一般情况下,对于重载方法的联合,正确的做法是什么并不明显。我认为有人可能希望通过自动扩大到只读联合数组来仅针对联合数组的情况,因为手动执行此操作是我通常建议的解决方法,而且它相当安全:

const arr2: readonly (string | number)[] = arr; // okay
arr2.every(() => true); // okay

但目前,这还没有发生。

Playgorund link to code

关于arrays - 为什么我可以调用 array.some() 而不是 array.every() 联合数组类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74390223/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com