Skip to content

Overloading arrow function return type should allow union type #33482

Closed
@joshuaavalon

Description

@joshuaavalon

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:

Activity

IllusionMH

IllusionMH commented on Sep 18, 2019

@IllusionMH
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.

joshuaavalon

joshuaavalon commented on Sep 19, 2019

@joshuaavalon
Author

@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

IllusionMH commented on Sep 19, 2019

@IllusionMH
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

mp3por commented on Jul 7, 2024

@mp3por

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @IllusionMH@mp3por@RyanCavanaugh@joshuaavalon

        Issue actions

          Overloading arrow function return type should allow union type · Issue #33482 · microsoft/TypeScript