Skip to content

Reducing union types when inferring type parameters in function invocations #4115

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

Closed
osdm opened this issue Aug 1, 2015 · 4 comments
Closed
Labels
Question An issue which isn't directly actionable in code

Comments

@osdm
Copy link

osdm commented Aug 1, 2015

Spec 3.4 says:

Union types are reduced to the smallest possible set of constituent types using these rules

But in compiler they are not reduced in case of inferring type parameters in function invocations. For example:

var o = {};

// According to spec, type of p should be reduced to {}
function f<T>(p: T | typeof o): T 
{
    var t: T;
    var temp = t || o; // here union type is reduced, and it is really {}
    return null;
}

// Another function where type of p is really {}. According to spec, it should be equal to f, shouldn't it?
function f2<T>(p: typeof o): T 
{
    return null;
}

// But really they are different
var e = f(5); // number
var e2 = f2(5); // {}

Could you please clarify, when union type are really reduced and when they are not.

@JsonFreeman
Copy link
Contributor

I imagine you are using the latest from master. Constituents in a union type are no longer reduced, at least not by the subtype relation. I believe this change is reflected in spec update #4033.

@JsonFreeman
Copy link
Contributor

And the code change for removing subtype reduction is #3823.

@ahejlsberg
Copy link
Member

Union types are reduced to the smallest possible set of constituent types using these rules

That paragraph has been removed from the spec.

I have yet to add a description of the new deduplication algorithm, but basically a type S is considered a duplicate of a type T if:

  • S and T are identical,
  • S is undefined,
  • S is null and T is not undefined,
  • S is an object literal type, T is an object type, and S has a property set that is a duplicate of T's,
  • S and T are array types, and S has an element type that is a duplicate of T's.
  • S and T are tuple types, and S has element types that are duplicates of T's.

In other words, we get rid of types that are identical to other types in the set, except they may have nulls or undefineds where the other types don't.

The implementation of this algorithm is in the removeDuplicateTypes function in checker.ts.

@osdm
Copy link
Author

osdm commented Aug 2, 2015

@JsonFreeman @ahejlsberg Thanks for updates!

@danquirk danquirk closed this as completed Aug 3, 2015
@danquirk danquirk added the Question An issue which isn't directly actionable in code label Aug 3, 2015
@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
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

4 participants