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

Intersected function type returns only first constituent's return type #10508

Closed
vsiao opened this issue Aug 23, 2016 · 5 comments
Closed

Intersected function type returns only first constituent's return type #10508

vsiao opened this issue Aug 23, 2016 · 5 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@vsiao
Copy link

vsiao commented Aug 23, 2016

TypeScript Version: 1.8/Playground

Code

interface A {
    a: boolean;
}
interface B {
    b: boolean;
}

declare const fooAB: (() => A) & (() => B);
const ab = fooAB(); // A

Expected behavior: ab has type A & B

Actual behavior: ab has type A

Perhaps this is being treated as an overloaded call signature, and () => A just happens to be first. If this is by design, it would be great to learn about any known workarounds.

cc @kevinder

@kitsonk
Copy link
Contributor

kitsonk commented Aug 24, 2016

this is covariance, right? dupe of #1394?

@mhegazy
Copy link
Contributor

mhegazy commented Aug 24, 2016

(() => A) & (() => B); is not equivalant to (() => A & B);.

(() => A) & (() => B); is equivalent to

declare const fooAB: {
    (): A;
    (): B
};

@mhegazy mhegazy added the Working as Intended The behavior described is the intended behavior; this is not a bug label Aug 24, 2016
@aluanhaddad
Copy link
Contributor

aluanhaddad commented Sep 4, 2016

@mhegazy I understand that the current behavior is practical, but the only way a function could actually implement the intersection would be by returning a value of A & B. Maybe it is not realistic but since, IIRC the compiler will always pick the first overload, it would be reasonable to expect the intersection.

@mhegazy
Copy link
Contributor

mhegazy commented Sep 7, 2016

The compiler has no way of merging signatures in the general case. this one seems simple enough, but what happens if there are parameters involved, what if they have different count, what if one of them is generic, what if the parameter types do not agree.. for instance
(a: number, b:string) => A and (a: string, b: number) => B is this (a: number|string, b: number|string) => A&B ? i do not think this is correct.

@mhegazy mhegazy closed this as completed Sep 7, 2016
@aluanhaddad
Copy link
Contributor

@mhegazy I agree that's not correct specifically because the functions have different parameter types. This means that using the union of each corresponding parameter is not accurate. Interestingly though, this also means that there is a way to select the overload that you want, so I don't think these signatures need to be merged.

Obviously it's not a trivial problem.

I think the intuitive behavior would be to only merge signatures when they match exactly in arity and parameter types.

My reasoning is that there's no way to statically select and thus differentiate between the different signatures that are available without using a type assertion.

@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
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants