-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Bugfix/union excess property check #54823
base: main
Are you sure you want to change the base?
Conversation
There is a bug microsoft#54784, which causes union types to behave inconsistenly when compared to the original types.
If the target type is an union, we'll check each type in the union. If any of the types ar assignable without excess properties, then that's the solution. We'll find those properties, which are assignable in at least one type and report those as causing the Object literal to be unassignable.
only in some cases in the union. The check was only performed when reporting was enbaled, which it isn;t in the first run of the funtion. This time it's done just after truly excess proprties have been reported. ---- TODO: - [ ] If there are excess properties in the intersection of the union types, then we'll receive the usual error only. If there are properties which will cause the obejct literal still being unassignable, these will not be reported yet. Function `hasExcess{Properties` might need splitting. But for now, it's acceptable.
@MartinJohns |
@yin Continuing discussion from #54784 (comment)... I'm not a TypeScript maintainer; it'd be better to discuss that kind of thing (error message wording, breaking changes, etc.) with someone on the team. As for the Flow example you gave, the behavior there seems straightforward enough, though I am concerned about performance and I'm sure the maintainers will be also. O(N*M) is effectively quadratic and the whole check itself is potentially cubic (number of types * number of properties of each * size of object literal) which could get ugly fast. |
type A = {a:number};
type B = {b:number};
let x: A|B = {a:0, b:0}; This being allowed is intentional behavior. Clearly an Excess property checks aren't intended to be a replacement for exact types. The goal here, generally speaking, is to prevent typos in property names. Code which is legal per the type system and doesn't contain an identifiable error should not be rejected. |
Devil’s advocate is that this reasoning applies equally to |
To expand on the above: if the formal line to be drawn is “the property exists on any of the union constituents” then that’s fine, but then EPC should probably reject an assignment of |
Before optimizing to sub-quadratic, wanted to experiment and discuss the topic. I'll keep this PR Draft until we address all issues. If we decide not to go forward, we might as well improve the baselines and/or docs based on our findings.
There are #20863 and #54784 so the community is confused and it's not explained. If TypeScript would do runtime type-checking and exact-type semantics, then My reasoning is that users don't expect current behavior. The reasons are not clear to them. They expect the Union type to behave as a true disjoint union and a dynamic one. I think It's OK to define |
@RyanCavanaugh I have read your comment, which motivated me to experiment with this code: #12936 (comment) Can you elaborate on what you meant with we'd prefer to fix that by making EPC smarter. in your comment about EPC? |
Let me re-phrase: |
IMO it’s not really useful to think of |
Understood, but FYI: I want to experiment so I want to keep this branch. Do
I need to close this Draft PRs?
…On Sat, 1 Jul 2023 at 21:14, Bruce Pascoe ***@***.***> wrote:
IMO it’s not really useful to think of | and & in terms of their effect
on object properties. If types are considered as sets of values, then A |
B is precisely the set union of A and B, while A & B is precisely the set
intersection. It’s true that & tends to create types which have the
properties of both members of the intersection, but here’s the key: *that
is a side effect of the type system allowing excess properties in general*
(any legal A can additionally have the properties of B and vice versa),
creating overlap. If A and B were exact types, then intersecting them
would tend to produce empty types, since there’d be no overlap in their
allowed values.
—
Reply to this email directly, view it on GitHub
<#54823 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACRYNKYHAEDEM3CM6ZNWNLXODYSXANCNFSM6AAAAAAZYDIAYE>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
--
Thank you
Kind regards,
Matej Sadovsky
Software Engineer
|
@yin would this bugfix address union EPC with tuple types, such as those in this example: #20863 (comment)? |
Fixes #54784
We'd like to improve the behavior of error messages for
Union
types. Currently, the compiler does not detect that object literal{a: ..., b: ...}
can't be assigned to either type in the unionA|B
:There is another #12936 which aims to solve the problem in general.
Please, do not merge yet.