microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
101.11k stars 12.5k forks source link

Reusing function type with different parameters amount (overloading) #45153

Open PabloSzx opened 3 years ago

PabloSzx commented 3 years ago

Bug Report

Is there any reason it's not possible to re-use a function type that is overloaded aka has different possible amount of arguments?

In the playground I put some code that shows this issue, but I will put a quick snippet here:

declare function foo(c: {a: number; b: string}): void
declare function foo(a: number, b: string): void

foo({ a: 1, b: "2" })

foo(1, "2")

// This doesn't work but is relatively understandable
const bar1: typeof foo = (a_c, b) => {
    a_c
    b
}

// This should work, why it doesn't?
const bar2: typeof foo = (...args) => {
    args
}

// it works fine, but you can't access the second parameter
const bar3: typeof foo = (a_c) => {  
    a_c
}

// it works fine, but you can't access the parameters
const bar4: typeof foo = () => {
}

bar2 in this example doesn't work, and the error that is given is Type '(args_0: number | { a: number; b: string; }, args_1: unknown) => void' is not assignable to type '{ (c: { a: number; b: string; }): void; (a: number, b: string): void; }'.

🔎 Search Terms

arguments overload parameter function

🕗 Version & Regression Information

In 4.4.0-beta & 4.3.5:

image

In 4.2.3 and before:

image

⏯ Playground Link

https://www.typescriptlang.org/play?target=99&jsx=0&ts=4.3.5#code/CYUwxgNghgTiAEAzArgOzAFwJYHtVJxwAowAueAbynNWQFsAjEGAbngfIGcMYtUBzAL4BKcgDccWYAFgAUKEiwEKdNjwFi1eLUbMANOy48+-UfAlS5V2YkJEK8LQEYDHeACIATO-gjrt4hcPb2FrAHow+AAVAAssTnhgHBBOVAByDHgAdxwYAGt2ZEz4+DhobDEQCABPeDRQGG4oVGAoBggQOTA8bnZYJ3IMaoAHEBxEDXgAXngiKAB9MFdhaYA+Sjl4LcdFze2GOUFwyNiSzhicZAhgbNy8gyyY2qxMpJT0jAB+Lp7MhlhPIMRmMJgFprMAHRQ2D8TgrKbrCh7LYwziHY7wF63fIJRB8ECuIrwaqXeBgZoZRxgMApBIYGIITjgPA3YawKB0EAYZg-VC9f4wADMQNG40mMzmi3hiK2yJ2YHRsjkEUxmRyOKQ+MJmRJyDJFMyUGptPg9IQbJgHK5zDRsm6fL+sAALCKQeLZtKNrIjrIgA

🙁 Actual behavior

It just errors out when trying to use "...args" to get all the possible arguments of the function

🙂 Expected behavior

To be able to use "...args" or similar to get the arguments and typescript to not complain just for trying to use it

RyanCavanaugh commented 3 years ago

bar2 should work and give args a type like [number, string] | [{a: number, b: string}]

ArtskydJ commented 1 year ago

I have a similar issue, but I replicated with an overloaded function with one argument:

type Foo = { a: boolean }
type Bar = { b: boolean }

declare function parse(query: Foo | Bar): void;
declare function parse(query: Bar): void; // 😵 If you swap this line with the line above, it works 😵

const foo: Foo = { a: true }
parse(foo) // 😎 It works as expected 😎

type Arguments = Parameters<typeof parse>
// I expect Arguments to be [ string | Foo | Bar ], but it is [ string | Bar ]

export const wrapped_parse = async(...args: Arguments) => parse(...args)

wrapped_parse(foo) // 😭 It does not work 😭
// Error:
// Argument of type 'Foo' is not assignable to parameter of type 'Bar'.
//   Property 'b' is missing in type 'Foo' but required in type 'Bar'.

TS Playground link