Uh oh!
There was an error while loading. Please reload this page.
Fix discriminant property check - #29110
Conversation
Wesley Wigham (weswigham)
commented
Dec 20, 2018
Based on your comment and the repro, isn't the real issue that we don't combine discriminant narrowing with other generated facts in control flow well? |
Anders Hejlsberg (ahejlsberg)
commented
Dec 20, 2018
Wesley Wigham (@weswigham) Well, yes and no. We would do better if we didn't have the design limitation that causes us to reset narrowed types for properties when the shape of an object changes because of a discriminant check, and we might in fact not have this issue. But it would require the ability to "record and replay" preceding narrowing checks, and that would definitely complicate the control flow analyzer. And, either way, there's really no point in considering |
Wesley Wigham (weswigham)
commented
Dec 20, 2018
In the given example, sure, but I can't help but feel that someone somewhere has taken a dependency on a property of |
Jack Williams (jack-williams)
commented
Dec 20, 2018
Anders Hejlsberg (@ahejlsberg) When you say:
What does shape mean: changing the apparent properties aggregated across the union type, or something else? Would it be too difficult (or wrong) to test for this change of shape, rather than classifying |
Anders Hejlsberg (ahejlsberg)
commented
Dec 20, 2018
Wesley Wigham (@weswigham) Discriminants are meant to be unit types and we only narrow based on equality and truthiness checks. With a discriminant of |
Wesley Wigham (weswigham)
commented
Dec 21, 2018
A |
Also 2-3 months != 2 weeks. This has been out for awhile (and has shipped in stable versions of TS). |
Wesley Wigham (@weswigham) No, we don't do discriminant based narrowing for typeFoo={a: string,x: number}|{a: 0,y: number};functionxxx(obj: Foo){if(typeofobj.a==="string"){obj.x;// Error (because we don't narrow here)}if(obj.a===0){obj.y;// Ok (discriminant based narrowing)}}With the fix in this PR our behavior changes in the following because we no longer consider typeFoo={a: string|undefined,x: number}|{a: string,y: number};functionxxx(obj: Foo){if(obj.a===undefined){obj.x;// Previously would narrow, now doesn't}}As I said, I can't imagine anyone having taken a dependency on this in the last few weeks (or months or whatever). This PR is the right fix for the issue given the design constraints we currently have. |
Jack Williams (jack-williams)
commented
Dec 21, 2018
If I understand the issue properly it seems to be a tradeoff between
The number of people affected by (1) seems likely to be larger than (2), and (2) can be fixed by replacing the equality test with a type guard. |
Anders Hejlsberg (ahejlsberg)
commented
Dec 21, 2018
Jack Williams (@jack-williams) Yes, that's the tradeoff. But #2 is actually even further qualified: Breaking code for early adopters of discriminant narrowing involving properties that have no single underlying property of a pure unit type or union of unit types. |
In #27695 we were slightly too permissive in what we consider a discriminant property. Specifically, we required the combined union type to contain at least one unit type, but that unit type could have occurred in combination with non-unit types. We now check that at least one underlying property has a pure unit type or union of unit types.
Fixes#29106.