【问题标题】:TypeScript sorting an array with union type elementTypeScript 对具有联合类型元素的数组进行排序
【发布时间】:2020-04-09 12:57:13
【问题描述】:
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

TryIt

【问题讨论】:

  • 我的猜测是你有两个数组的联合类型,而不是联合类型的数组:(A[] | B[]) vs (A | B)[]

标签: typescript


【解决方案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 的函数必须接受 As 或 Bs 但不能同时接受两者。唯一可能的函数将接受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

【讨论】:

    【解决方案2】:

    列表可以是任一

    { version: number, a: string }[]
    

    { version: number, b: string }[]
    

    这意味着如果你只提供一个空数组

    list = []
    

    它不能确定它的类型。

    要修复它,只需告诉 typescript 你正在使用哪个:

    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;
    })
    

    【讨论】:

    • 相反,TS 知道确切是什么类型。它是{ version: number, a: string }[]{ version: number, b: string }[]。这里没有混淆。
    猜你喜欢
    • 1970-01-01
    • 2011-12-18
    • 2017-08-25
    • 2019-12-24
    • 1970-01-01
    • 2014-06-22
    • 1970-01-01
    • 2012-04-15
    • 2013-09-05
    相关资源
    最近更新 更多