TypeScript使用联合类型元素对数组进行排序

时间:2020-04-09 12:57:13

标签: typescript

const list: ({ version: number, a: string }[]) | ({ version: number, b: string }[]) = [];

// Parameter 'a' implicitly has an 'any' type.(7006)
list.sort((a, b) => { 
    return a.version - b.version;
})

为什么将参数ab推导到any

enter image description here

2 个答案:

答案 0 :(得分:1)

原因是您拥有数组的并集 ,这会导致您观察到问题。

让我们通过命名类型使代码更加清晰。以后再讨论它们会容易得多:

type A = { version: number, a: string };
type B = { version: number, b: string };

因此,您拥有的是list: (A[] | B[]),而不是(A | B)[]。两者具有不同的语义-后者确实意味着您可以在单个数组中混合使用AB类型,而您只允许一个数组。但是,打字方面有所不同。

TypeScript 确实识别出您拥有的并集的所有成员都是数组,因此list.sort()是现有方法。实际上,它是两种方法-一种来自A[],另一种来自B[]。但是,为了确保类型安全,TypeScript将合并两个.sort()方法的签名。

签名希望将这些回调传递进来:

type sortA = (x: A, y: A) => number;
type sortB = (x: B, y: B) => number;

因此,为了合并两者,TypeScript将使用

type mergedSort = sortA & sortB

这会导致问题-实现mergedSort的函数必须接受AB,但不能同时接受。唯一可以执行此操作的函数将接受any类型,因为它满足限制。

因此,为什么要获得any的推断类型-它是唯一可以与任一数组一起使用的类型。

相比之下,如果您有(A | B)[],则.sort()方法的回调看起来像这样:

type sortMixed = (x: A | B, y: A | B): number;

由于联合中的类型共享version属性,因此可以有效地使用它:

type A = { version: number, a: string };
type B = { version: number, b: string };

const list: (A | B)[] = [];

list.sort((a, b) => {
    return a.version - b.version;
});

Playground Link

答案 1 :(得分:0)

列表可以是

{ version: number, a: string }[]

{ version: number, b: string }[]

这意味着如果您仅为其提供一个空数组

list = []

不能确定其类型。

要解决此问题,只需告诉打字稿您使用的是哪个:

const list: ({ version: number, a: string }[]) | ({ version: number, b: string }[]) = [];

// compiles
(list as ({ version: number, a: string }[])).sort((a, b) => { 
    return a.version - b.version;
})