为什么 TypeScript 联合类型 + 映射类型在有泛型和没有泛型时表现不同
我刚开始使用泛型。以下代码的“w0”和“w1”不同,但代码看起来一样。
它们为什么不同,以及我如何以相反的方式得到相反类型。
我已经查看了一些文件,但找不到任何解释,有没有哪份文件可以解释它们不同类型的原理?
我如何在没有 Calc 和 Generics 的情况下得到 Calc<BaseA> | Calc<BaseB>。
我如何使用 泛型 获得 { type: "A" | "B"; flag: number; }。
type BaseA = {
type: 'A'
name: string
flag: number
}
type BaseB = {
type: 'B'
id: number
flag: number
}
type Base = BaseA | BaseB
type w0 = {
[k in keyof Base]: Base[k]
}
/*
w0 = {
type: "A" | "B";
flag: number;
}
*/
type Calc<W> = {
[k in keyof W]: W[k]
}
type w1 = Calc<Base>
/*
w1 = Calc<BaseA> | Calc<BaseB>
*/
type z0 = Exclude<w0,BaseA>
// z0 = w0
type z1 = Exclude<w1,BaseA>
// z1 = BaseB
答案#1
第一个问题很容易解决:
type Q1 = {
[B in Base as B["type"]]: {
[K2 in keyof B]: B[K2]
}
}[Base["type"]]
// type Q1 = {
// type: 'A';
// name: string;
// flag: number;
// } | {
// type: 'B';
// id: number;
// flag: number;
// }
我们首先对 Base 中的每个元素进行映射,并将 type 键作为结果类型的键。对于每个元素,我们可以映射元素的键。最后,我们使用 Base["type"] 索引此类型以获取联合类型。
你现在可以用 Calc 替换内部映射。
type Q1 = {
[B in Base as B["type"]]: Calc<B>
}[Base["type"]]
// type Q1 = Calc<BaseA> | Calc<BaseB>
第二个问题有点棘手。它是由分配条件类型引起的。我发现只有使用这个技巧才能禁用分配性:
type Calc2<W extends [any]> = {
[k in keyof W[0]]: W[0][k]
}
type Q2 = Calc2<[Base]>
// type Q2 = {
// type: "A" | "B";
// flag: number;
// }
操场
