Home > Blockchain >  [first, ...rest]: A spread argument must either have a tuple type or be passed to a rest parameter.t
[first, ...rest]: A spread argument must either have a tuple type or be passed to a rest parameter.t

Time:01-09

Setting

class X {
    constructor(first: string, ...rest: string[]) { }
}

new X(...["foo", "bar"])

yields the error

A spread argument must either have a tuple type or be passed to a rest parameter.ts(2556)

This is working:

new X("foo", ...["bar"])

but that's not very handy.

If I use

class X {
    constructor(...all: string[]) { }
}

instead it's working fine, so it must have something to do with me splitting into first and rest. But is there a way to make this work with split arguments?

CodePudding user response:

The type of ["foo", "bar"] is string[]. If you can't control the type of this with as const, because you got it elsewhere, you can validate and narrow the type, for example:

const input:string[] = ["foo", "bar"];

if (!input.length<1) {
  throw new Error('Input must at least have 1 element');
}
const tuple: [string, ...string[]] = [input[0], ...input.slice(1)];
}

If the assignment feels silly, I feel this is way more elegant:

const input:string[] = ["foo", "bar"];

function assertAtLeast1Element(input: string[]): asserts input is [string, ...string[]] {
  if (input.length < 1) throw new Error('Input must at least have 1 element');
}

assertAtLeast1Element(input);

class X {
    constructor(first: string, ...rest: string[]) { }
}

new X(...input);
  • Related