英文:
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.
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 a result.
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论