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

Attempt to fix #9919 - Intersecting discriminated union breaks type narrowing #9939

Closed
wants to merge 3 commits into from

Conversation

gcnew
Copy link
Contributor

@gcnew gcnew commented Jul 25, 2016

Fixes #9919.

This PR adds support for correctly narrowing discriminated unions that are also intersected. As a side effect a type is now eligible for discrimination whenever it is a union or intersection, regardless whether the discrimination property is a union itself. This is to handle situations where the property type is narrowed by subsequent intersections.

@msftclas
Copy link

Hi @gcnew, I'm your friendly neighborhood Microsoft Pull Request Bot (You can call me MSBOT). Thanks for your contribution!

In order for us to evaluate and accept your PR, we ask that you sign a contribution license agreement. It's all electronic and will take just minutes. I promise there's no faxing. https://cla.microsoft.com.

TTYL, MSBOT;

@RyanCavanaugh
Copy link
Member

@ahejlsberg want to take a look?

@msftclas
Copy link

@gcnew, Thanks for signing the contribution license agreement so quickly! Actual humans will now validate the agreement and then evaluate the PR.

Thanks, MSBOT;

@ahejlsberg
Copy link
Member

@gcnew Thanks for your contribution!

We're about to merge #9407 which contains a number of changes in this area, including optimizations to improve performance in code bases with large union types (100+ constituent types) such as would result if we convert the compiler itself to depend on these features. Merging that will undoubtedly affect this PR. Not sure if you've looked at that already.

One concern I have with incorporating intersection types is that I will cause even more types to be generated by narrowing operations, thus negatively affecting performance. Also, if we go beyond just the top level of union types we really should handle any arbitrary number of nested unions and intersections, e.g. ((A | B) & (C | D) | (E | F) & (G | H)). And of course we'd need to make sure that all the different kinds of narrowing are covered. It's definitely not a simple task.

@@ -8095,7 +8106,7 @@ namespace ts {
}
const propName = propAccess.name.text;
const propType = getTypeOfPropertyOfType(type, propName);
if (!propType || !isStringLiteralUnionType(propType)) {
if (!propType || !(isStringLiteralUnionType(propType) || (type.flags & TypeFlags.UnionOrIntersection))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't want to narrow if the original type was a union? That doesn't sound right.

Copy link
Contributor Author

@gcnew gcnew Jul 26, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, maybe the better way to write it is:

if (!propType || (!isStringLiteralUnionType(propType) && (type.flags & TypeFlags.UnionOrIntersection) === 0))

i.e. if neither the discrimination property is a string-literal-union, nor the parent type is a union or intersection. I guess I made it unintelligible by applying De Morgan's law.

@gcnew
Copy link
Contributor Author

gcnew commented Jul 26, 2016

@ahejlsberg Thank you for taking a look at this PR!

Yes, I'm following #9407 and I suspect that this code will not be compatible with what's to come.

I agree that complete support of arbitrary ADT/intersection blending will have memory and performance implications especially if done naively as I did here. On the other hand, features like this one make TypeScript more expressive than ML-like languages. If we can isolate the performance hit to affect only the rare users/use cases that consciously take advantage of this functionality will that be an acceptable compromise? After all having type casts and vanished type-safety is arguably worse.

@mhegazy mhegazy self-assigned this Sep 14, 2016
@gcnew
Copy link
Contributor Author

gcnew commented Oct 19, 2016

This behaviour is being implemented in #11717. Closing this one in favour of the latter.

@gcnew gcnew closed this Oct 19, 2016
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants