1

I actually think this is a bug, but I thought I'd ask. I have a function. If passes a single number, I want to perform an operation that returns two objects. If it receives two numbers, I want to return one object. This looks like this now:

function split (splitAt: number | [number, number]): SomeSplittableObject | [SomeSplittableObject, SomeSplittableObject]

but with overloading I should be able to do this:

function split (splitAt: number): [SomeSplittableObject, SomeSplittableObject]
function split (splitAt: [number, number]): SomeSplittableObject
function split (splitAt: number | [number, number]): SomeSplittableObject | [SomeSplittableObject, SomeSplittableObject] {
    // ... Implementation
}

let splitAt: number | [number, number] //... some variable
split(splitAt)

but I get an in-editor error

No overload matches this call.
  Overload 1 of 2, '(splitAt: [number, number]): SomeSplittableObject', gave the following error.
    Argument of type 'number | [number, number]' is not assignable to parameter of type '[number, number]'.
      Type 'number' is not assignable to type '[number, number]'.
  Overload 2 of 2, '(splitAt: number): [SomeSplittableObject, SomeSplittableObject]', gave the following error.
    Argument of type 'number | [number, number]' is not assignable to parameter of type 'number'.
      Type '[number, number]' is not assignable to type 'number'.

even if I cast splitAt as any in the implementation args I get the error

1
  • Why would they be a bug? Your variable is deliberately typed to make overload resolution ambiguous and the implementation signature never counts towards the overload set Commented Oct 16, 2019 at 19:01

1 Answer 1

4

The line that is causing your error is this one:

let splitAt: number | [number, number] //... some variable

With the overloading signature that you have, you are saying that you have two forms of the function split. One that takes a number and the other that takes an array with two numbers. You do not have a signature that takes both types and therefore the compiler is complaining.

split(1) // return type is [SomeSplittableObject, SomeSplittableObject]
split([1,2]) // return type is SomeSplittableObject

let splitAt: number | [number, number] //... some variable
split(splitAt) // return type is ???

Edit

Note that when overloading a function, the implemented function signature is shadowed by the overloads and not visible to the outside. In your case above, you only had 2 options. If you want to add the third option where the input/output is "ambiguous", you need to add the signature as an overload (I used shorter types here for clarity):

function foo(x: number): Foo;
function foo(x: string): Bar;
// Define an overload in which the inputs and outputs can be either type
function foo(x: string | number): Foo | Bar;
// Function signature is shadowed by overloads defined above.
function foo(x: string | number): Foo | Bar { /* ... */ } 
Sign up to request clarification or add additional context in comments.

2 Comments

is function split (splitAt: number | [number, number]): SomeSplittableObject | [SomeSplittableObject, SomeSplittableObject] not a form that takes both?
@FranklinHarvey I added an edit to address your comment.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.