1

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.

E_net4
  • 27,810
  • 13
  • 101
  • 139
blitter
  • 347
  • 5
  • 21
  • 1
    `constructor (…params: any[])` – jsejcksn Feb 12 '22 at 16:23
  • Does this answer your question? [Spreading an array in a typescript function: Error TS2556](https://stackoverflow.com/questions/68884073/spreading-an-array-in-a-typescript-function-error-ts2556) – Emma Feb 12 '22 at 16:42
  • With constructor `(...args: any[])` still `this.init(...args);` throws the same error. – blitter Feb 12 '22 at 17:20

1 Answers1

3

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);
}

Try it.

Parzh from Ukraine
  • 7,999
  • 3
  • 34
  • 65
  • 1
    How would I use the `Parameters` helper to get the parameters of the superclass's constructor? I tried `constructor (...args: Parameters) { super(...args); }` but it fails with `Type 'Function' provides no match for the signature '(...args: any): any'.ts(2344)`. `Parameters` gets me back to the TS2556 error. – blitter May 24 '22 at 14:30
  • 2
    For that there's `ConstructorParameters` – Parzh from Ukraine May 24 '22 at 20:44