英文:
returning an Array of tuples using map on an Array in Typescript
问题
I have an Array const x:number[] = [1,2,3,4,5]
and I'm trying to obtain an array of tuples containing the original value in x
and a value obtained by mapping a function on it.
我的目标是获取一个包含 x
中原始值和映射函数产生的值的元组数组。
My attempt was something like this
我的尝试是类似这样的:
pos = x.map(xi => (
[xi, 3*xi]
))
This returns pos
as of type number[][]
but I want a [number, number]
as result.
这会将 pos
返回为 number[][]
类型,但我想要的是 [number, number]
作为结果。
Do you know how to fix this code?
你知道如何修复这段代码吗?
英文:
I have an Array const x:number[] = [1,2,3,4,5]
and I'm trying to obtain an array of tuples containing the original value in x
and a value obtained by mapping a function on it.
My attempt was something like this
pos = x.map(xi => (
[xi, 3*xi]
))
This returns pos
as of type number[][]
but I want a [number, number]
as result.
Do you know how to fix this code?
答案1
得分: 1
默认情况下,TypeScript 会将像 [xi, 3 * xi]
这样的 数组字面量 推断为无序的 数组类型,长度可以是任意的,比如 number[]
,而不是 元组类型,比如 [number, number]
。 这通常是人们所期望的,因为数组比元组更常见。 当这种推断不合适时,您需要采取措施来告诉编译器要做其他的事情。
有多种方法可以实现这一点。 如果您明确想要 [number, number]
,那么最直接的方法是为 Array.prototype.map
方法 手动指定 U
类型参数,该方法的声明如下(在这里声明):
interface Array<T> {
map<U>(cb: (v: T, i: number, a: T[]) => U, thisArg?: any): U[];
}
像这样:
const x: number[] = [1, 2, 3, 4, 5];
const pos = x.map<[number, number]>(xi => (
[xi, 3 * xi]
));
// const pos: [number, number][]
但通常情况下,您可以要么手动注释分配字面值的变量:
const pos = x.map(xi => {
const ret: [number, number] = [xi, 3 * xi];
return ret;
});
// const pos: [number, number][]
要么您可以使用 const
断言 来让编译器改变其推断算法,以更喜欢字面类型和readonly
元组:
const pos = x.map(xi => [xi, 3 * xi] as const);
// const pos: (readonly [number, number])[]
readonly [number, number]
类型与 [number, number]
不完全相同,但根据您的用例,它可能足够了。
英文:
By default, TypeScript will see an array literal like [xi, 3 * xi]
and infer its type to be an unordered array type of arbitrary length like number[]
, and not a tuple type like [number, number]
. That's often what people want, since arrays are more common than tuples. When such inference isn't suitable, you'll need to do something to ask the compiler to do something else.
There are a number of ways to do this. If you explicitly want [number, number]
, then the most straightforward approach is to manually specify the U
type argument for the Array.prototype.map
method which is declared like:
interface Array<T> {
map<U>(cb: (v: T, i: number, a: T[]) => U, thisArg?: any): U[];
}
Like this:
const x: number[] = [1, 2, 3, 4, 5];
const pos = x.map<[number, number]>(xi => (
[xi, 3 * xi]
));
// const pos: [number, number][]
But in general, you can either manually annotate the variable to which you're assigning the literal:
const pos = x.map(xi => {
const ret: [number, number] = [xi, 3 * xi];
return ret;
});
// const pos: [number, number][]
or you could use a const
assertion to get the compiler to change its inference algorithm to prefer literal types and readonly
tuples:
const pos = x.map(xi => [xi, 3 * xi] as const);
// const pos: (readonly [number, number])[]
The type readonly [number, number]
is not identical to [number, number]
, but depending on your use case it might suffice.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论