1

Shouldn't Omit<T, keyof U> & U be equal to just T? Or am I missing something?

Here is an example, where this issue arises:

interface Bar {
  bar: string;
}

class Foo<T extends Bar> {
  foo(obj: Omit<T, keyof Bar>): T {
    return { ...obj, bar: 'bar' }; // compile error
  }
}

This is the error message from the Typescript compiler:

Type Pick<T, Exclude<keyof T, "bar">> & { bar: string; } is not assignable to type T. Pick<T, Exclude<keyof T, "bar">> & { bar: string; } is assignable to the constraint of type T, but T could be instantiated with a different subtype of constraint Bar.


Of course one could simply cast it and it would work. Like so:

class Foo<T extends Bar> {
  foo(obj: Omit<T, keyof Bar>): T {
    return { ...obj, bar: 'bar'} as T; // this works
  }
}

But should this casting be necessary?


The expression { ...obj, bar: 'bar' } is inferred to be Omit<T, keyof Bar> & Bar. But, after all, is that not an alias for T? How could T ever be instantiated with a different subtype of constraint Bar?

To summarize,

if Omit<T, keyof Bar> is picking every member of T, excluding the one's existing in Bar,

How is the intersection of the types Omit<T, keyof Bar> and Bar not just T?

Francisco
  • 157
  • 7

0 Answers0