Closed
Description
I'm using union type expression to express the result of merging two objects. however it's being optimized in a way that changes (over-eager?) type inference behavior.
TypeScript Version:
3.0.0-dev.20180616 , 2.9.1-insiders.20180525
Search Terms:
union optimization inference merge
Code
I've tried to simplify it as much as I can while still keeping some 'real-world' relevance.
type Argument<T> = {
[P in keyof T]: T[P]; // in the real use case it's `[P in keyof T]: SomeType<T[P]>`
};
class Context<T> {
constructor(private arg: Argument<T>) {
}
get<T1 extends keyof T>(key: T1): T[T1]{
return this.arg[key]; // in the real use case it's `this.arg[key].something()`
}
}
declare function merge2<T1, T2>(arg1: Argument<T1>, arg2: Argument<T2>): Argument<T1 | T2>;
let a = merge2({foo: { foobar: true }}, {foo: { foobar: 4 }});
const res = new Context(a).get('foo').foobar;
Expected behavior:
I expect this code to compile, and res to be of type number | boolean
Actual behavior:
Compilation fails .
using a custom union type expression works, however:
// replaces T1 | T2 expression in the type of merge2's result
type Union<T1, T2> = {
[P in keyof (T1| T2)]: P extends keyof T1 ? P extends keyof T2 ? T1[P] | T2[P]: T1[P] : P extends keyof T2 ? T2[P] : never;
}
Playground Link:
the bug
Related Issues:
#18043