Я думаю, что ваша проблема, вероятно, вызвана тем, что встроенная утилита типа Omit<T, K>
, как и Pick<T, K>
, не распространяет через союзы в T
. Вы, кажется, ожидаете (что не является необоснованным), что Omit<A | B, K>
должно быть эквивалентно Omit<A, K> | Omit<B, K>
, но это не работает таким образом. Вместо этого Omit<A | B, K>
сопоставляется с keyof (A | B)
, что совпадает с (keyof A) & (keyof B)
, и вы обнаруживаете, что видите только общие свойства.
Самым простым решением для этого является создание версии Omit
, которая распространяет по объединениям, используя распределительный условный тип . Если у вас есть универсальный параметр типа c T
, то конструкция T extends any ? F<T> : never
в итоге будет распределять операцию F<>
по T
, когда T
является типом объединения. Вот определение:
type DistributiveOmit<T, K extends PropertyKey> = T extends any ? Omit<T, K> : never;
Вы можете проверить, что DistributiveOmit<A | B, K>
теперь будет в точности эквивалентно DistributiveOmit<A, K> | Distributive<B, K>
. И, таким образом, DistributiveOmit<TEvent, "refs">
будет сам союз:
function foo(event: DistributiveOmit<TEvent, "refs">) {
switch (event.type) {
case Events.Set: {
event.state; // okay
break;
}
case Events.Toggle: {
break;
}
case Events.UpdateContext: {
event.context; // okay
}
}
}
Хорошо, надеюсь, это поможет; удачи!
Детская площадка ссылка на код