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.

3
  • 1
    constructor (…params: any[]) Commented Feb 12, 2022 at 16:23
  • Does this answer your question? Spreading an array in a typescript function: Error TS2556 Commented Feb 12, 2022 at 16:42
  • With constructor (...args: any[]) still this.init(...args); throws the same error. Commented Feb 12, 2022 at 17:20

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

How would I use the Parameters helper to get the parameters of the superclass's constructor? I tried constructor (...args: Parameters<MySuperClass["constructor"]>) { super(...args); } but it fails with Type 'Function' provides no match for the signature '(...args: any): any'.ts(2344). Parameters<MySuperClass["MySuperClass"]> gets me back to the TS2556 error.
For that there's ConstructorParameters<MySuperClass>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.