Callback with variable number of arguments, is converted into a function with a single argument
Opened this issue · 0 comments
A function with a variable number of arguments, passed as argument to another function, gets converted into a function with just a single argument:
declare function call(f: (...args: number[]) => void): void;gets converted to
type [<AllowNullLiteral>] IExports =
abstract call: f: (ResizeArray<float> -> unit) -> unitI think the idea is for ResizeArray to contain all passed arguments. But it's actually just the first argument:
function call(f: (...args: number[]) => void): void {
f(3, 5)
}let [<Global>] call (f: ResizeArray<float> -> unit): unit = jsNative
call (fun args -> printfn "Args=%A" args)Output:
args=3
Even worse: What is ResizeArray<float> in F#, is actually float during runtime -- which means functions of ResizeArray will fail at runtime or produce unexpected results:
call (fun args -> printfn "Length=%i" args.Count)
// Length=0
call (fun args -> for arg in args do printfn "* %f" arg)
// Uncaught TypeError: xs[Symbol.iterator] is not a functionEspecially confusing when args is a type compatible to array during runtime like string:
function call(f: (...args: string[]) => void): void {
f("Alpha", "Beta")
}let [<Global>] call (f: ResizeArray<string> -> unit): unit = jsNative
call (fun args -> printfn "args=%A" args)
call (fun args -> printfn "Length=%i" args.Count)
call (fun args -> for arg in args do printfn "* %s" arg)Output:
args=Alpha
Length=5
* A
* l
* p
* h
* a
-> only first argument -> iterating over characters of first string
Probably even more confusing with ...args: any[] instead of a fixed type.
I'm not sure what the correct code would be.
... in TS/JS is [<ParamArray>] in F# -- but Attributes aren't allowed here.
Currently the best option is probably to create an overload for each expected call by hand. But for that one must know with how many arguments the function gets called. (And it isn't auto-generated)