test.js
:
export class MyClass {
constructor () {
this.init(...arguments);
}
init(arg, opts) {
console.log(arg, opts);
}
}
The above is perfectly valid JavaScript ES6 code. In TypeScript, you'd define the argument types:
test.ts
:
export class MyClass {
constructor () {
this.init(...arguments); // this no worky
}
init(arg: string, opts: Object) {
console.log(arg, opts);
}
}
But the typescript version has a problem with this.init(...arguments);
. It complains (local var) arguments: IArguments A spread argument must either have a tuple type or be passed to a rest parameter.ts(2556)
.
How do I pass down "all arguments no matter what" down to the sub function, while avoiding the ugly apply(this, args)
construct?
I know I could specifically name all parameters, given that there are 2 here, but let's assume in my real application, both constructor()
and init()
must be able to accept a huge amount of parameters. Even if all parameters were known, it's tedious and verbose to repeat all parameters and their types in typescript, over and over, in each cascading sub function call level, when you already know they will only be passed down and handled by sub function init()
anyway.
It was suggested that this Spreading an array in a typescript function: Error TS2556 already answers this question. So I tried this:
test2.ts
:
export class MyClass {
constructor (...args: any[]) {
this.init(...args); // STILL throws the TS2556 error
}
init(arg: string, opts: Object) {
console.log(arg, opts);
}
}
It still throws the TS2556 error.
CodePudding user response:
The problem is that there's not enough information for TypeScript to be sure about the correctness of the types: arguments
is not properly typed, and ...args: any[]
is explicitly saying "an array with some number of whatever". You have to add this information by yourself, and you can do this with the built-in Parameters
helper:
constructor (...args: Parameters<MyClass["init"]>) {
this.init(...args);
}