Repository navigation
TS4.1.2 Regression: Incorrect arity inferred on function returned by util.callbackify if input function has optional or default argument #41607
Copy link
Copy link
Closed
Labels
Has ReproThis issue has compiler-backed repros: https://aka.ms/ts-reprosThis issue has compiler-backed repros: https://aka.ms/ts-reprosWorking as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bug
Description
TypeScript Version: v4.2.0-dev.20201119. Also impacts: 4.1.2. Does not impact: 4.1.0-beta, 4.0.5
Search Terms:
callbackify expected arguments optional default
Code
import util from 'util';
function functionWithDefaultArgReturnsPromise(arg1: number, arg2: string, arg3: boolean = false): Promise<number> {
return new Promise<number>((resolve, reject) => {
// do something
});
}
const functionWithDefaultArgHasCallBack = util.callbackify(functionWithDefaultArgReturnsPromise)
functionWithDefaultArgHasCallBack(1, 'two', true, (err: any, result: any) => {
// do something
// this callback function triggers error
//
// "Expected 3 arguments, but got 4.(2554)"
//
// in the v4.2.0-dev.20201119 (nightly at the time in the playground),
// but not with 4.1.0-beta in the playground, but I do see it on 4.1.2 locally as well as the last release candidate.
});Expected behavior:
No error, no red squiggly lines
Actual behavior:
Error "Expected 3 arguments, but got 4.(2554)" occurs with red squiggly underlines on the callbackified function.
Related Issues:
No related issue found.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Has ReproThis issue has compiler-backed repros: https://aka.ms/ts-reprosThis issue has compiler-backed repros: https://aka.ms/ts-reprosWorking as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bug
Activity
[-]Incorrect type inferred when calling util.callbackify on function that returns Promise[/-][+]Incorrect type inferred when calling util.callbackify on function with optional or default argument that returns Promise[/+][-]Incorrect type inferred when calling util.callbackify on function with optional or default argument that returns Promise[/-][+]Regression: Incorrect function arity inferred on function returned by util.callbackify if input function has optional or default argument[/+][-]Regression: Incorrect function arity inferred on function returned by util.callbackify if input function has optional or default argument[/-][+]Regression: Incorrect arity inferred on function returned by util.callbackify if input function has optional or default argument[/+][-]Regression: Incorrect arity inferred on function returned by util.callbackify if input function has optional or default argument[/-][+]TS4.1.2 Regression: Incorrect arity inferred on function returned by util.callbackify if input function has optional or default argument[/+]orta commentedon Nov 25, 2020
Here's a compiler backed repro:
Workbench Repro
typescript-bot commentedon Nov 25, 2020
👋 Hi, I'm the Repro bot. I can help narrow down and track compiler bugs across releases! This comment reflects the current state of the repro in this issue running against the nightly TypeScript.
Comment by Orta Therox (@orta)
❌ Failed: -
Expected 3 arguments, but got 4.Parameter 'err' implicitly has an 'any' type.Parameter 'result' implicitly has an 'any' type.Historical Information
Comment by ben (@whoisbenli)
❌ Failed: -
Expected 3 arguments, but got 4.Parameter 'err' implicitly has an 'any' type.Parameter 'result' implicitly has an 'any' type.👍 Compiled
ahejlsberg commentedon Dec 1, 2020
This is an effect of #41308. With that PR we made our handling of optional parameters in overload ladders more consistent. For example:
It has to do with some pretty strange behavior in the subtype relation which we use in the first pass of overload resolution. Previously we didn't consider
(x: number, y?: number) => voidto be a subtype of(x: number) => void, but strangely we did consider(x: number, y?: any) => voidand(x: number, y?: unknown) => voidto be a subtypes. We now consider all of them subtypes. It's definitely more consistent, but it ends up subtly changing which overloads we pick in overload ladders when the source has optional parameters.To put it in context of the OP example above, pre-4.1 we report an error when the function signature is changed to
i.e. if type
unknownis used instead ofbooleanfor the optional argument. That seems very inconsistent. In 4.1 we consistently pick the first overload that matches, which means we consider the optional argument to be omitted.ahejlsberg commentedon Dec 3, 2020
BTW, root cause of this issue is the same as #41563.
typescript-bot commentedon Nov 21, 2021
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.