我刚开始使用泛型。下面的代码有不同的“w0”和“w1”,但代码看起来是一样的。
为什么它们不同,以及我如何以相反的方式获得相反的类型。
我查了一些文档,但没有找到任何解释,有没有文档可以解释它们不同类型的原理?
我怎样才能得到Calc<BaseA> | Calc<BaseB>
没有Calc
和Generics
.
我怎样才能得到{ type: "A" | "B"; flag: number; }
与 Generics
.
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
最佳答案
第一个问题很容易解决:
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
替换内部 map 。
type Q1 = {
[B in Base as B["type"]]: Calc<B>
}[Base["type"]]
// type Q1 = Calc<BaseA> | Calc<BaseB>
第二个问题有点棘手。这是由 Distributive Conditional Types 引起的。我发现只能用这个技巧来禁用分配性:
type Calc2<W extends [any]> = {
[k in keyof W[0]]: W[0][k]
}
type Q2 = Calc2<[Base]>
// type Q2 = {
// type: "A" | "B";
// flag: number;
// }
关于typescript - 为什么 Typescript Union + 映射类型在使用和不使用泛型的情况下工作方式不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72810324/