Skip to content
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

Assignment fails for types with conditional lookup for a union of a generic #32816

Closed
smoogly opened this issue Aug 12, 2019 · 3 comments
Closed
Labels
Duplicate An existing issue was already created

Comments

@smoogly
Copy link

smoogly commented Aug 12, 2019

TypeScript Version: Version 3.6.0-dev.20190810

Search Terms: union conditional lookup

Code

type Target<T> = T extends null ? null : T;
type Target2<T> = { "one": null, "two": T }[T extends null ? "one" : "two"];
type Target3<T> = [null, T][T extends null ? 0 : 1];

function tst<T extends string>() {
    // These two pass as expected:
    const case0: Target2<T | null> = 1 as any as Target2<T | null>;
    const case1: { prop: Target<T | null> } = 1 as any as { prop: Target<T | null> };
    const case2: { prop: Target2<T> } = 1 as any as { prop: Target2<T> };
    const case3: { prop: Target3<T> } = 1 as any as { prop: Target3<T> };

    // These two fail as expected:
    const case4: { prop: Target2<T> } = 1 as any as { prop: Target2<T | null> };
    const case5: { prop: Target3<T> } = 1 as any as { prop: Target3<T | null> };

    // These two are expected to pass, but fail:
    const case6: { prop: Target2<T | null> } = 1 as any as { prop: Target2<T | null> };
    const case7: { prop: Target3<T | null> } = 1 as any as { prop: Target3<T | null> };
}

Expected behavior:
Expected cases 6 and 7 to pass, as both sides of assignment supposed to be structurally identical.

Actual behavior:
Cases 6 and 7 fail. Example output:

error TS2719: Type '{ prop: { "one": null; "two": T | null; }["one" | (T extends null ? "one" : "two")]; }' is not assignable to type '{ prop: { "one": null; "two": T | null; }["one" | (T extends null ? "one" : "two")]; }'. Two different types with this name exist, but they are unrelated.
  Types of property 'prop' are incompatible.
    Type '{ "one": null; "two": T | null; }[T extends null ? "one" : "two"] | null' is not assignable to type 'null & { "one": null; "two": T | null; }[T extends null ? "one" : "two"]'.
      Type '{ "one": null; "two": T | null; }[T extends null ? "one" : "two"]' is not assignable to type 'null & { "one": null; "two": T | null; }[T extends null ? "one" : "two"]'.
        Type 'T | null' is not assignable to type 'null & { "one": null; "two": T | null; }[T extends null ? "one" : "two"]'.
          Type 'T' is not assignable to type 'null & { "one": null; "two": T | null; }[T extends null ? "one" : "two"]'.
            Type 'string' is not assignable to type 'null & { "one": null; "two": T | null; }[T extends null ? "one" : "two"]'.
              Type 'string' is not assignable to type 'null'.
                Type 'T' is not assignable to type 'null'.
                  Type '{ "one": null; "two": T | null; }[T extends null ? "one" : "two"]' is not assignable to type 'null'.
                    Type 'T | null' is not assignable to type 'null'.
                      Type 'T' is not assignable to type 'null'.
                        Type 'string' is not assignable to type 'null'.

Playground Link

Related Issues: #30152 looks similar

@AnyhowStep
Copy link
Contributor

Feels a little bit like this #32442

Except yours does not use function params.

@jack-williams
Copy link
Collaborator

jack-williams commented Aug 12, 2019

This is a consequence of #30769 and fundamentally the same issue as discussed in #31833, however the trigger is slightly different.

The instantiation of the distributive conditional type T extends null ? "one" : "two" is "one" | (T extends null ? "one" : "two") as the conditional distributes over the union. The union key causes the index access type in the target type to simplify to an intersection (despite the property never being assigned), as per #30769.

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Aug 16, 2019
@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

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
5 participants