从联合类型中提取,其中鉴别器也是联合

我有这样的类型:

enum Type {
  A = 'A',
  B = 'B',
  C = 'C'
}

type Union =
 | {
     type: Type.A | Type.B;
     key1: string
   }
 | {
     type: Type.C;
     key2: string
   }

type EnumToUnionMap = {
  [T in Type]: {
    [k in keyof Extract<Union, {type: T}>]: string
  }
}

我遇到的问题typeof EnumToUnionMap[Type.A]never(实际上,它是一个通用的键签名,[x: string]: string但那是因为当是或时Extract<Union, {type: T}>返回类型)而是neverTType.AType.Btypeof EnumToUnionMap[Type.C]

{
  type: Type.C,
  key2: string
}

正如预期的那样。

这一切都是有道理的,因为typeinEnumToUnionMap[Type.A]Type.A | Type.BType.A != (Type.A | Type.B)所以它们不匹配,我们得到never.

基本上我需要做这样的事情:

type EnumToUnionMap = {
  [T in Type]: {
    [k in keyof Extract<Union, T in Union['type']>]: string
  }
}

为什么我需要这样做:

我收到来自具有以下形状的警报端点的响应:

{
 type: Type,
 key1: string,
 key2: string
}

Type.AType.B提供的警报key1同时Type.C提供key2
我需要将响应中的键映射到网格中的列名(其中某些警报类型共享一组通用键,但列的显示名称不同):

const columnMap: EnumToUnionMap = {
  [Type.A]: {
    key1: 'Column name'
    // Note that in actuality this object will contain
    // multiple keys (i.e. multiple columns) for a
    // given `Type` so creating a map
    // between `Type -> column name` is not possible.
  },
  [Type.B]: {
    key1: 'Different column name'
  },
  [Type.C]: {
    key2: 'Another column name'
  }
}

这样,我可以执行以下操作:

const toColumnText = (alert) => columnMap[alert.type]

...

if (alert.type === Type.A) {
  const key1ColumnName = toColumnText(alert).key1 // typed as string
  const key2ColumnName = toColumnText(alert).key2 // Typescript warns of undefined key
}

以上是从联合类型中提取,其中鉴别器也是联合的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>