Skip to content

Union type conflicts with overloaded function #16816

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
donaldpipowitch opened this issue Jun 29, 2017 · 4 comments
Closed

Union type conflicts with overloaded function #16816

donaldpipowitch opened this issue Jun 29, 2017 · 4 comments
Labels
Duplicate An existing issue was already created

Comments

@donaldpipowitch
Copy link
Contributor

TypeScript Version: 2.4.1

Code

type Foo = { bar: string };

declare function foos(f: Foo);
declare function foos(f: Foo[]);

function foos2(f: Foo | Foo[]) {
  foos(f);
  // Argument of type 'Foo | Foo[]' is not assignable to parameter of type 'Foo[]'.
  //  Type 'Foo' is not assignable to type 'Foo[]'.
  //    Property 'length' is missing in type 'Foo'.
}

Expected behavior:

foos accepts Foo and Foo[]. foos2 accepts Foo | Foo[]. I think foos2 can just pass its argument to foos without problems.

Actual behavior:

Argument of type 'Foo | Foo[]' is not assignable to parameter of type 'Foo[]'.
  Type 'Foo' is not assignable to type 'Foo[]'.
    Property 'length' is missing in type 'Foo'.
@jcalz
Copy link
Contributor

jcalz commented Jun 29, 2017

I've wondered about unions/intersections of parameters to overloaded/generic functions before. My guess is that it's a good thing to want but might be too expensive for the type checker to do this. Can anyone link to a canonical issue for this type of thing?

Of course in your case you can work around this in any number of ways. The best way is probably to declare the function to take Foo | Foo[] in the first place instead of overloading it.

If you are trying to fix without redeclaring the function, you can cast it:

function foos2(f: Foo | Foo[]) {
  (foos as (f: Foo | Foo[]) => any)(f); // success
}

And in general, you can force TypeScript to notice that an overloaded or generic function can take a union:

var intersectFunction:
  <A1, R1, A2, R2> (func: ((a: A1) => R1) & ((a: A2) => R2)) => ((a: A1 | A2) => R1 | R2)
  = (func => func);

function foos2(f: Foo | Foo[]) {
  intersectFunction<Foo,any,Foo[],any>(foos)(f); // success
};

I agree it would be nice if TypeScript just noticed without being forced to. It doesn't, because _________________________ (someone fill in the blank pls, thx!)

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Jun 29, 2017
@RyanCavanaugh
Copy link
Member

Tracked at #14107 and #1805.

What search terms did you use? I'd like to edit their titles so people can find them more easily

@jcalz
Copy link
Contributor

jcalz commented Jun 29, 2017

If I search for "generic", "overload", "union", and "intersection", issue #14107 is in the top several results, so it was probably just myopia on my part. Thanks!

@mhegazy
Copy link
Contributor

mhegazy commented Aug 17, 2017

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@mhegazy mhegazy closed this as completed Aug 17, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants