我定义这个类型的方式有什么问题
type Payload<Es> = {
trigger:
Es extends Record<infer K, infer V>
? { key: K, data: V } : never
}
type Evs = {
"item.1": { ok: "Y", code: number }
"item.2": 1 | 0
}
const payload: Payload<Evs> = {
trigger: {
key: "item.1",
data: 1
}
}
payload.trigger.data
没有像我预期的那样推断出来
预计
{ ok: "Y", code: number }
我得到了什么
0 | { ok: "Y", code: number } | 1
Record<K, V>
实用程序类型是与具有类型K
属性键和V
类型属性值的对象相对应的类型。但特定的键不与特定的值关联。如果您从 {a: string, b: number}
开始,并尝试从中推断 Record<K, V>
,您将得到 Record<"a" | "b", string | number>
。这与您从 {a: number, b: string}
获得的类型相同。所以你真的不想在这里推断出Record
,除非你想要将所有属性混合在一起。
相反,您实际上只需要映射类型,迭代每个键
K
,并生成相应的对象类型,然后索引到映射的类型以获得属性的联合。也就是说,您需要一个分布式对象类型(如microsoft/TypeScript#47109中所创造):
type Payload<E> = {
trigger: { [K in keyof E]: { key: K, data: E[K] } }[keyof E]
}
您可以验证这是否为您提供了您正在寻找的内容:
type Evs = {
"item.1": { ok: "Y", code: number }
"item.2": 1 | 0
}
type PEvs = Payload<Evs>;
/* type PEvs = {
trigger: {
key: "item.1";
data: {
ok: "Y";
code: number;
};
} | {
key: "item.2";
data: 0 | 1;
};
} */
const payload: Payload<Evs> = {
trigger: {
key: "item.1",
data: 1 // error!
}
}