Skip to content

union optimization #25037

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
amir-arad opened this issue Jun 18, 2018 · 2 comments
Closed

union optimization #25037

amir-arad opened this issue Jun 18, 2018 · 2 comments
Labels
Duplicate An existing issue was already created

Comments

@amir-arad
Copy link

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

@mhegazy
Copy link
Contributor

mhegazy commented Jun 21, 2018

I think the union type you had there is not correct.. Argument<T1 | T2> should be Argument<T1> | Argument<T2> since you can not have a transformation on the union, but rather a union of the transformations.

That said. the behavior of failing inference if it comes up with non-matching candidates is something that we thought about changing, but did not seem like the right move. you can find more discussion and reasoning in #20339 and #19596.

@mhegazy mhegazy added the Duplicate An existing issue was already created label Jun 21, 2018
@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants