从联合类型中提取,其中鉴别器也是联合
我有这样的类型:
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.B,Type.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.A和Type.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
}