Допустим, у меня есть следующие различающиеся союзы и некоторые связанные типы
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}
Я не понимаю, где ошибка, потому что, если я заменяю типы, то онадолжно сработать.Существует только 2 значения для K
при приеме двойного дополнения, поэтому давайте попробуем первое
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>}