Array.prototype.sort() 不保留元组的元素类型

问题描述 投票:0回答:1

简单的示例按预期工作:

type Data = {
    a: number
    b: number
}

const data: Data[] = [
    {a :1, b: 1},
    {a: 2, b: 2}
].sort((el1, el2) => el1.a - el2.a)

排序工作,类型被保留。

但它不适用于元组数组:

type Data = [number, number]

const data: Data[] = [ // error: Type number[][] is not assignable to type Data[]
    [1, 2],
    [3, 4]
].sort((a, b) => a[0] - b[0])

对于异质物品,情况更糟:

type Data = [number, boolean]

const data: Data[] = [ // error: Type '(number | boolean)[][]' is not assignable to type 'Data[]'
    [1, true],
    [3, false]
].sort((a, b) => a[0] - b[0])
//      ^? (parameter) a: (number | boolean)[]

我的类型在概念上是错误的吗?或者这是一个已知的限制,如果是,有解决方法吗?

我知道

.sort()
会改变数组。但由于顶级 不是 元组,我希望 TypeScript 保留结果类型并正确推断
.sort()
内部元素的类型。

typescript
1个回答
0
投票

为了

const data: Data[] = [[1, 2], [3, 4]].sort((a, b) => a[0] - b[0]);

要按原样工作,TypeScript 需要通过 contextuallyData[] 的预期返回类型传播回

通过
sort() 的调用来推断
数组文字 
的类型,以便看到
 [[1, 2], [3, 4]]
也必须是
Data[]
。 但上下文类型推断并不总是通过这种方式调用方法进行回溯。 这是语言的限制。类似的问题可以在 microsoft/Typescript#29771microsoft/TypeScript#47440 中看到。

相反,

[[1, 2], [3, 4]]
最终会得到默认的非上下文推断类型
number[][]
,然后
sort()
返回
number[][]
,并且赋值失败。


可以通过多种方式解决这个问题,所有这些方法都涉及开发人员指定更明确的类型,而不是依赖于推理。

我的建议是使用

 
[[1, 2], [3, 4]]
 运算符
:
Data[]
提供
satisfies

的上下文类型
const data: Data[] = ([
  [1, 2],
  [3, 4]
] satisfies Data[]).sort((a, b) => a[0] - b[0]) // okay

你也可以直接写

const data = ([
  [1, 2],
  [3, 4]
] satisfies Data[]).sort((a, b) => a[0] - b[0]) // okay

并且

data
的推断类型将等同于
Data[]
。这两个版本的优点是不更改运行时代码(加上或减去一些括号)并且相对类型安全(而不是使用
as
类型断言运算符
)。

Playground 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.