typescript 从数组生成联合类型

64jmpszr  于 2023-02-25  发布在  TypeScript
关注(0)|答案(1)|浏览(204)

我想从ALL_RESPONSE_TYPES数组中生成union,代码如下:

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 应该可以做到这一点。

56lgkhnf

56lgkhnf1#

你可以创建一个Map的数组类型,将ALL_RESPONSE_TYPES的类型转换为type/metadata对象的数组类型,然后将index into类型与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类型时,使用the typeof type query operator,它会给你想要的ResponseType

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

Playground代码链接

相关问题