英文:
get string literals out of const array after flatMap on it
问题
我已声明一个数组为const:
const cloudRegionItems = [
{
category: 'Google Cloud',
regions: [
{ value: 'v2018-us-central1', label: 'us-central1' },
{ value: 'europe-west1', label: 'europe-west1' },
],
},
{
category: 'Amazon Web Services',
regions: [
{ value: 'us-east-1', label: 'us-east-1' },
{ value: 'us-west-2', label: 'us-west-2' },
],
},
] as const;
然后,我想要展平上述数组的regions。我这样做:
const cloudRegionOptions = cloudRegionItems.flatMap((item) => item.regions);
但是我遇到了以下错误:
Type 'readonly [{ readonly value: "v2018-us-central1"; readonly label: "us-central1"; }, { readonly value: "europe-west1"; readonly label: "europe-west1"; }] | readonly [{ readonly value: "us-east-1"; readonly label: "us-east-1"; }, { ...; }]' is not assignable to type '{ readonly value: "v2018-us-central1"; readonly label: "us-central1"; } | { readonly value: "europe-west1"; readonly label: "europe-west1"; } | readonly ({ readonly value: "v2018-us-central1"; readonly label: "us-central1"; } | { ...; })[]'.
Type 'readonly [{ readonly value: "us-east-1"; readonly label: "us-east-1"; }, { readonly value: "us-west-2"; readonly label: "us-west-2"; }]' is not assignable to type 'readonly ({ readonly value: "v2018-us-central1"; readonly label: "us-central1"; } | { readonly value: "europe-west1"; readonly label: "europe-west1"; })[]'.
Type '{ readonly value: "us-east-1"; readonly label: "us-east-1"; } | { readonly value: "us-west-2"; readonly label: "us-west-2"; }' is not assignable to type '{ readonly value: "v2018-us-central1"; readonly label: "us-central1"; } | { readonly value: "europe-west1"; readonly label: "europe-west1"; }'.
Type '{ readonly value: "us-east-1"; readonly label: "us-east-1"; }' is not assignable to type '{ readonly value: "v2018-us-central1"; readonly label: "us-central1"; } | { readonly value: "europe-west1"; readonly label: "europe-west1"; }'.
Type '{ readonly value: "us-east-1"; readonly label: "us-east-1"; }' is not assignable to type '{ readonly value: "europe-west1"; readonly label: "europe-west1"; }'.
Types of property 'value' are incompatible.
Type '"us-east-1"' is not assignable to type '"europe-west1"'.
在这个TS Playground链接中可以找到示例。
英文:
I have declared an array as const:
const cloudRegionItems = [
{
category: 'Google Cloud',
regions: [
{ value: 'v2018-us-central1', label: 'us-central1' },
{ value: 'europe-west1', label: 'europe-west1' },
],
},
{
category: 'Amazon Web Services',
regions: [
{ value: 'us-east-1', label: 'us-east-1' },
{ value: 'us-west-2', label: 'us-west-2' },
],
},
] as const;
Then I want to flatten the regions of above mentioned array. I am doing it like this:
const cloudRegionOptions = cloudRegionItems.flatMap((item) => item.regions);
But I am getting an error as mentioned here:
Type 'readonly [{ readonly value: "v2018-us-central1"; readonly label: "us-central1"; }, { readonly value: "europe-west1"; readonly label: "europe-west1"; }] | readonly [{ readonly value: "us-east-1"; readonly label: "us-east-1"; }, { ...; }]' is not assignable to type '{ readonly value: "v2018-us-central1"; readonly label: "us-central1"; } | { readonly value: "europe-west1"; readonly label: "europe-west1"; } | readonly ({ readonly value: "v2018-us-central1"; readonly label: "us-central1"; } | { ...; })[]'.
Type 'readonly [{ readonly value: "us-east-1"; readonly label: "us-east-1"; }, { readonly value: "us-west-2"; readonly label: "us-west-2"; }]' is not assignable to type '{ readonly value: "v2018-us-central1"; readonly label: "us-central1"; } | { readonly value: "europe-west1"; readonly label: "europe-west1"; } | readonly ({ readonly value: "v2018-us-central1"; readonly label: "us-central1"; } | { ...; })[]'.
Type 'readonly [{ readonly value: "us-east-1"; readonly label: "us-east-1"; }, { readonly value: "us-west-2"; readonly label: "us-west-2"; }]' is not assignable to type 'readonly ({ readonly value: "v2018-us-central1"; readonly label: "us-central1"; } | { readonly value: "europe-west1"; readonly label: "europe-west1"; })[]'.
Type '{ readonly value: "us-east-1"; readonly label: "us-east-1"; } | { readonly value: "us-west-2"; readonly label: "us-west-2"; }' is not assignable to type '{ readonly value: "v2018-us-central1"; readonly label: "us-central1"; } | { readonly value: "europe-west1"; readonly label: "europe-west1"; }'.
Type '{ readonly value: "us-east-1"; readonly label: "us-east-1"; }' is not assignable to type '{ readonly value: "v2018-us-central1"; readonly label: "us-central1"; } | { readonly value: "europe-west1"; readonly label: "europe-west1"; }'.
Type '{ readonly value: "us-east-1"; readonly label: "us-east-1"; }' is not assignable to type '{ readonly value: "europe-west1"; readonly label: "europe-west1"; }'.
Types of property 'value' are incompatible.
Type '"us-east-1"' is not assignable to type '"europe-west1"'.
Here is the playground: TS Playground link
答案1
得分: 1
问题在于当你对 item.regions
使用 flatMap
时,结果的类型是一个可变数组类型。由于 item.regions
是一个只读元组类型,因此赋值出现错误。你可以通过先映射,然后扁平化(与 flatMap
相同)来轻松解决这个问题:
const cloudRegionOptions = cloudRegionItems.map((item) => item.regions).flat();
这样做的原因是 map
的结果被推断为只读元组数组,而由于所有的 item.regions
都是只读元组,所以赋值有效。在映射之后,你可以扁平化数组,从而获得期望的结果。
英文:
The problem is that when you flatMap
item.regions
, the resulting type is a mutable array type. Since item.regions
is a readonly tuple type, the assignment is broken, and an error occurs. You can easily get around this by mapping first, then flattening (which is the same as flatMap
):
const cloudRegionOptions = cloudRegionItems.map((item) => item.regions).flat();
This works since the result from map
is inferred as an array of readonly tuples, and since all item.regions
are readonly tuples, the assignment works. After you map, you can then flatten the array, which produces the desired result.
答案2
得分: 0
我不知道我在TypeScript中在做什么,但在游乐场中,以下两者似乎都可以工作:
const cloudRegionOptions = cloudRegionItems.flatMap((item): Readonly<Array<any>> => item.regions);
和
const cloudRegionOptions = cloudRegionItems.flatMap((item) => [...item.regions])
英文:
I have no idea what I'm doing in Typescript but both of the following seem to work in the playground:
const cloudRegionOptions = cloudRegionItems.flatMap((item): Readonly<Array<any>> => item.regions);
and
const cloudRegionOptions = cloudRegionItems.flatMap((item) => [...item.regions])
答案3
得分: 0
.map(...).flat()
是解决这个问题的最佳方式,但也可以使用flatMap(...)
的替代声明来正确推断狭窄类型:
interface ReadonlyArray<T> {
flatMap<U extends (unknown | ReadonlyArray<unknown>), This = undefined> (
callback: (this: This, value: T, index: number, array: T[]) => U,
thisArg?: This
): U extends ReadonlyArray<unknown> ? U : U[]
}
英文:
.map(...).flat()
is the best way to work around this, but an alternative declaration for flatMap(...)
can also infer the correctly narrowed type:
interface ReadonlyArray<T> {
flatMap<U extends (unknown | ReadonlyArray<unknown>), This = undefined> (
callback: (this: This, value: T, index: number, array: T[]) => U,
thisArg?: This
): U extends ReadonlyArray<unknown> ? U : U[]
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论