提取`flatMap`后的常量数组中的字符串文字。

huangapple go评论72阅读模式
英文:

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.

Playground

答案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&lt;Array&lt;any&gt;&gt; =&gt; item.regions);

and

const cloudRegionOptions = cloudRegionItems.flatMap((item) =&gt; [...item.regions])

答案3

得分: 0

.map(...).flat()是解决这个问题的最佳方式,但也可以使用flatMap(...)的替代声明来正确推断狭窄类型:

interface ReadonlyArray&lt;T&gt; {
    flatMap&lt;U extends (unknown | ReadonlyArray&lt;unknown&gt;), This = undefined&gt; (
        callback: (this: This, value: T, index: number, array: T[]) =&gt; U,
        thisArg?: This
    ): U extends ReadonlyArray&lt;unknown&gt; ? 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&lt;T&gt; {
    flatMap&lt;U extends (unknown | ReadonlyArray&lt;unknown&gt;), This = undefined&gt; (
        callback: (this: This, value: T, index: number, array: T[]) =&gt; U,
        thisArg?: This
    ): U extends ReadonlyArray&lt;unknown&gt; ? U : U[]
}

huangapple
  • 本文由 发表于 2023年3月31日 03:24:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/75892215.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定