生成联合类型从一个数组

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

Generate union type from an array

问题

我想从 `ALL_RESPONSE_TYPES` 数组生成联合类型。
具有以下代码:
```typescript
interface MetadataAccepted {
  a: string;
  b: number;
}
interface MetadataIgnored {
  c: number;
  d: string;
  e: {
    a: string
  }
}

const ALL_RESPONSE_TYPES = [
  ['ACCEPTED', { a: '', b: 0 } as MetadataAccepted],
  ['IGNORED', { c: 0, d: '', e: {a: ''} } as MetadataIgnored],
] as const;

我想创建以下类型:

type ResponseType =
  | {
      type: 'ACCEPTED';
      metadata: {
        a: string;
        b: number;
      };
    }
  | {
      type: 'IGNORED';
      metadata: {
        c: number;
        d: string;
        e: { a: string }
      };
    };

我相信在 TypeScript 中应该可以实现这一点。


<details>
<summary>英文:</summary>

I want to generate union from the `ALL_RESPONSE_TYPES` array.
Having the following code:
```typescript
interface MetadataAccepted {
  a: string;
  b: number;
}
interface MetadataIgnored {
  c: number;
  d: string;
  e: {
    a: string
  }
}

const ALL_RESPONSE_TYPES = [
  [&#39;ACCEPTED&#39;, { a: &#39;&#39;, b: 0 } as MetadataAccepted],
  [&#39;IGNORED&#39;, { c: 0, d: &#39;&#39;, e: {a: &#39;&#39;} } as MetadataIgnored],
] as const;

I want to create the following type:

type ResponseType =
  | {
      type: &#39;ACCEPTED&#39;;
      metadata: {
        a: string;
        b: number;
      };
    }
  | {
      type: &#39;IGNORED&#39;;
      metadata: {
        c: number;
        d: string;
        e: { a: string }
      };
    };

I believe it should be possible to achieve this in typescript.

答案1

得分: 1

你可以创建一个映射数组类型,将ALL_RESPONSE_TYPES的类型转换为type/metadata对象的数组类型,然后使用number索引进入该类型以获得联合类型。就像这样:

type R<T extends readonly (readonly [any, any])[]> =
  { [I in keyof T]: { type: T[I][0], metadata: T[I][1] } }[number];

R实用类型将类似[[0, 1], [2, 3], [4, 5]]的对数数组类型转换为类似[{type:0, metadata:1},{type: 2, metadata: 3},{type: 4, metadata: 5}]的对象数组,然后索引进入它以获得联合类型{type:0, metadata:1} | {type: 2, metadata: 3} | {type: 4, metadata: 5}

当它作用于ALL_RESPONSE_TYPES的类型时,使用typeof类型查询运算符,它将为您提供所需的ResponseType

type ResponseType = R<typeof ALL_RESPONSE_TYPES>;
/* type ResponseType = {
  type: "ACCEPTED";
  metadata: MetadataAccepted;
 } | {
  type: "IGNORED";
  metadata: MetadataIgnored;
 } */

代码播放链接

英文:

You can make a mapped array type that transforms the type of ALL_RESPONSE_TYPES to an array type of type/metadata objects, and then index into that type with number to get a union. Like this:

type R&lt;T extends readonly (readonly [any, any])[]&gt; =
  { [I in keyof T]: { type: T[I][0], metadata: T[I][1] } }[number];

The R utility type converts an array type of pairs like [[0, 1],[2, 3],[4, 5]] into an array of objects like [{type:0, metadata:1},{type: 2, metadata: 3},{type: 4, metadata: 5}] and then indexes into it to get the union {type:0, metadata:1} | {type: 2, metadata: 3} | {type: 4, metadata: 5}.

And when it acts on the type of ALL_RESPONSE_TYPES, using the typeof type query operator, it gives you the desired ResponseType:

type ResponseType = R&lt;typeof ALL_RESPONSE_TYPES&gt;;
/* type ResponseType = {
  type: &quot;ACCEPTED&quot;;
  metadata: MetadataAccepted;
 } | {
  type: &quot;IGNORED&quot;;
  metadata: MetadataIgnored;
 } */

Playground link to code

huangapple
  • 本文由 发表于 2023年2月24日 01:02:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/75548017.html
匿名

发表评论

匿名网友

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

确定