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

Overloading arrow function return type should allow union type #33482

Closed
joshuaavalon opened this issue Sep 18, 2019 · 4 comments
Closed

Overloading arrow function return type should allow union type #33482

joshuaavalon opened this issue Sep 18, 2019 · 4 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@joshuaavalon
Copy link

TypeScript Version: v3.5.1 (On TypeScript Playground)

Search Terms:

Arrow function overload

Code

const foo1 : {
    (a: number): number;
    (a: string): string;
} = (a: number | string): number | string => a;

// Type '(a: string | number) => string | number' is not assignable to type '{ (a: number): number; (a: string): string; }'.
//   Type 'string | number' is not assignable to type 'number'.
//     Type 'string' is not assignable to type 'number'.

const foo2 : {
    (a: number): number;
    (a: string): string;
} = (a: number | string): number & string => a as any;

function foo3(a: number): number;
function foo3(a: string): string;
function foo3(a: number | string): number | string {
    return a;
}

Expected behavior:

The return value of implementation of overloading arrow function should be number | string which is allowed with function.

Actual behavior:

TypeScript expect the return value of implementation of overloading arrow function should be number & string.

Playground Link:

Link

Related Issues:

@IllusionMH
Copy link
Contributor

This is correct error.
If you check how you should use result of this function (result of the implementation, skip overloads for now because implementation has no knowledge of input->output types mapping) you would expect that implementation will support both of this cases without type errors.

const a: number = foo1(someNum);
const a: string = foo1(someStr);

this can be achieved only by a type that is assignable to number and string at the same time and this is number & string.
If you'll have function that has signature (a: number | string) => number | string e.g.

(a: number | string) => Math.random() > 0.5 ? Number(a) : String(a);

then it won't work in case described above.

In case of foo1 you can use

const foo1 : {
    (a: number): number;
    (a: string): string;
} = (a: number | string): any => a;
                          ^^^

But users will see only 2 correct signatures.

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Sep 18, 2019
@joshuaavalon
Copy link
Author

joshuaavalon commented Sep 19, 2019

@IllusionMH My problem is the result is not consistent with function.

For example,

function foo3(a: number): number;
function foo3(a: string): string;
function foo3(a: number | string): number[] | string {
    return a;
}

It shows

This overload signature is not compatible with its implementation signature.

The error is on the overload signature.

However, the error in arrow function overload is on the implementation signature. As a result, function can return string | number or string & number without error.

If I use any, I will lose the type check on return type.

@IllusionMH
Copy link
Contributor

It can't be consistent with functions with current syntax. Function overloads has special syntax and therefore can provide special handling of return types.

Your examples are regular function assignment and without special syntax are indistinguishable from incorrect implementations.

type Overloaded = {
    (a: number): number;
    (a: string): string;
};

declare function correct(a: number | string): number & string;
declare function incorrect(a: number | string): number | string;

const f1: Overloaded = correct;
const f2: Overloaded = incorrect; // correctly errors

You don't want to allow second case.

To request similarity you should create proper feature request/proposal with convincing use cases, instead of using Bug report template.

@mp3por
Copy link

mp3por commented Jul 7, 2024

How is it possible that the "correct" function returns string & number at the same time ? The type C = A & B in TS is used to tell the compiler that the variable of type C will be both A and B at the same time, correct ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
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