【发布时间】:2019-05-04 10:30:29
【问题描述】:
假设我有以下区分联合和一些关联类型
type Union = 'a' | 'b';
type Product<A extends Union, B> = { f1: A, f2: B};
type ProductUnion = Product<'a', 0> | Product<'b', 1>;
现在我可以通过使用映射类型和Exclude来获取补码
type UnionComplement = {
[K in Union]: Exclude<Union, K>
};
// {a: "b"; b: "a"}
type UnionComplementComplement = {
[K in Union]: Exclude<Union, Exclude<Union, K>>
};
// {a: "a"; b: "b"}
到目前为止,所有这些都是有道理的,但是当我尝试采用双重补码时,ProductUnion 的事情就崩溃了。第一个补码效果很好
type ProductComplement = {
[K in Union]: Exclude<ProductUnion, { f1: K }>
};
// {a: Product<'b', 1>; b: Product<'a', 0>}
无论我尝试什么,双补码都不正确
type ProductComplementComplement = {
[K in Union]: Exclude<ProductUnion, Exclude<ProductUnion, { f1: K }>>
};
// {a: ProductUnion; b: ProductUnion}
我不明白错误在哪里,因为如果我替换类型,那么它应该可以工作。 K 取双补时只有 2 个值,所以让我们尝试第一个
type First = Exclude<ProductUnion, Exclude<ProductUnion, { f1: 'a' }>>;
// {f1: 'a'; f2: 0}
第二个也可以
type Second = Exclude<ProductUnion, Exclude<ProductUnion, { f1: 'b' }>>;
// {f1: 'b'; f2: 1}
所有组成部分都可以工作,但在映射类型中组合时,它似乎崩溃了。我在这里错过了什么?
一时兴起,我尝试添加一个类型参数,以通过抽象补充过程来查看会发生什么
type Complementor<T> = {
[K in Union]: Exclude<T, { f1: K }>
};
type DoubleComplementor<T> = {
[K in Union]: Exclude<T, Exclude<T, { f1: K }>>
};
现在,如果我将参数化类型应用于 ProductUnion,它将完全按照我的预期工作
type Complement = Complementor<ProductUnion>;
// {a: Product<'b', 1>; b: Product<'a', 0>}
type DoubleComplement = DoubleComplementor<ProductUnion>;
// {a: Product<'a', 0>; b: Product<'b', 0>}
【问题讨论】:
-
这是非常奇怪的行为,据我所知,编译器停止分发
Exclude的T参数 .. 不知道为什么 .. 可能是一个错误。 -
奇怪...我找不到任何关于嵌套分布式类型无法像这样工作的 GitHub 问题。就好像编译器在进行分发之前过于激进地简化了一些事情。可能值得提出问题。
-
谢谢各位。我将在今天晚些时候打开一个问题来跟进。
-
那么@TitianCernicova-Dragomir @jcalz 这里的预期/正确输出是什么?
ProductComplementComplement或DoubleComplement之一 -
@AravindanVe OP 所期望的行为也是我所期望的。
标签: typescript discriminated-union typescript-types