I have an issue with union types and Exclude (playground link):
type Foo = {
data: string;
otherData: number;
};
type Bar = Omit<Foo,'otherData'>
// type Bar = { data: string; }; // Even this is not working
type FooBar = Foo | Bar;
type ShouldBeFoo = Exclude<FooBar, Bar>; // Not working
// ShouldBeFoo = never
type ShouldBeBar = Exclude<FooBar, Foo>; // Somehow working
// ShouldBeBar = { data: string }
Am I missing something related to union types and/or Exclude?
I also tried with TS 4.4 and 4.2 with the same result.
Note:
We discovered the issue using type guards, you can see it in the playground here.
Exclude excludes types that are matching, not equal.
You are excluding Bar from FooBar. Bar matches Bar and Bar matches Foo. So you exclude both.
You could use something such as
type ExcludeExact<T, U> = T extends U ? U extends T ? T : never : never
Utility types like Pick, Omit work well with interface or types with properties since the second arg looks of keyof K.
As yours is a union type, the TS compiler is unable to infer the correct behavior. You can try this
type Foo = {
data: string;
otherData: number;
};
type Bar = Omit<Foo, 'otherData'>
type FooBar = Foo | Bar;
type Reduce<T, K> = T extends K ? K : never;
type ShouldBeFoo = Reduce<FooBar, Foo>;
type ShouldBeBar = Reduce<FooBar, Bar>;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With