-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Error message improvements for unions with identical discriminants #42598
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at this again, it's way more arguable. I think part of the approach that might be failing is that we're stopping at the first type, and not continuously refining the union of types given to us.
foo2({ | ||
type2: 'y', | ||
~~~~~~~~~~ | ||
!!! error TS2345: Argument of type '{ type2: "y"; value: "done"; method(): void; }' is not assignable to parameter of type 'X2 | Y2'. | ||
!!! error TS2345: Object literal may only specify known properties, but 'type2' does not exist in type 'X2'. Did you mean to write 'type1'? | ||
value: 'done', | ||
method() { | ||
this; | ||
this.value; | ||
} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a new error - I'd argue this is actually a regression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, isn’t this perfectly assignable to Y2
?
~~~~~~~~~~~ | ||
!!! error TS2322: Type '{ p1: "left"; p2: true; p3: number; p4: string; }' is not assignable to type 'DisjointDiscriminants'. | ||
!!! error TS2322: Object literal may only specify known properties, and 'p4' does not exist in type '{ p1: "left"; p2: true; p3: number; }'. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is definitely an improvement.
amb = { tag: "A", y: 12 } | ||
~~~~~ | ||
!!! error TS2322: Type '{ tag: "A"; y: number; }' is not assignable to type 'Ambiguous'. | ||
!!! error TS2322: Object literal may only specify known properties, and 'y' does not exist in type '{ tag: "A"; x: string; }'. | ||
amb = { tag: "A", x: "hi", y: 12 } | ||
~~~~~ | ||
!!! error TS2322: Type '{ tag: "A"; x: string; y: number; }' is not assignable to type 'Ambiguous'. | ||
!!! error TS2322: Object literal may only specify known properties, and 'y' does not exist in type '{ tag: "A"; x: string; }'. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are...ambiguous! Unclear if they should error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, why should they be errors? Particularly the previous error on amb = { tag: "A", y: 12 }
seems super wrong. But this one too seems like excess property checking is a little overzealous. For non-discriminated unions of objects, excess property checking only complains about properties non present in any constituent. Here, I would think the same rule would apply after we have filtered out the B and C constituents. So you should be allowed to supply x: string
and y: number
, but not z: boolean
.
~~~~~~~~~ | ||
~~~~~ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regression
amb = { tag: "A", z: true } | ||
~~~ | ||
~~~~~~~ | ||
!!! error TS2322: Type '{ tag: "A"; z: true; }' is not assignable to type 'Ambiguous'. | ||
!!! error TS2322: Type '{ tag: "A"; z: true; }' is not assignable to type '{ tag: "B"; z: boolean; }'. | ||
!!! error TS2322: Types of property 'tag' are incompatible. | ||
!!! error TS2322: Type '"A"' is not assignable to type '"B"'. | ||
!!! error TS2322: Object literal may only specify known properties, and 'z' does not exist in type '{ tag: "A"; x: string; }'. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is sort of an improvement - ideally, we'd be able to say that z
was in another branch.
@typescript-bot pack this |
Heya @andrewbranch, I've started to run the tarball bundle task on this PR at a3b8ad2. You can monitor the build here. |
Hey @andrewbranch, I've packed this into an installable tgz. You can install it for testing by referencing it in your
and then running There is also a playground for this build and an npm module you can use via |
This experiment is pretty old, so I'm going to close it to reduce the number of open PRs. |
This PR would fix #40934, but we will be changing the core logic used in #42556.
However, I'm opening this because I wanted to point out the sorts of
improvementschanges we can see though if we're willing do a little extra work to track multiple object types with identical discriminants though. That logic can possibly be incorporated into #42556.