Search code examples
javascriptarraystypescriptfunctionobject

TS2556: A spread argument must either have a tuple type or be passed to a rest parameter. Using in Object.assign


So I have this function:

export default function getObjectFromTwoArrays(keyArr: Array<any>, valueArr: Array<any>) {
  // StartPoint:
  //  [key1,key2,key3],
  //  [value1,value2,value3]
  //
  // EndPoint: {
  //  key1: value1,
  //  key2: value2,
  //  key3: value3
  // }

  if (keyArr.length === valueArr.length) {
    // @ts-ignore
    return Object.assign(...keyArr.map((el,index) => ({[el]: valueArr[index]})))
  } else {
    throw new Error(`Arrays should be the same length: ${{keyArr}}, ${{valueArr}}`)
  }
}

So me need to get exact this result from example above - EndPoint. I tried to expand to a variable, got the same issue.

I tried to to replace with: Object.assign({...keyArr.map((el,index) => ({[el]: valueArr[index]}))})

But the result will be: {0: {key1: value1}, 1: {key2: value2}}

Also with Object.assign([...keyArr.map((el,index) => ({[el]: valueArr[index]}))])

Result: [{key1: value1}, {key2: value2}]


Solution

  • The Object.assign method takes at least one parameter, but in your function the array you were spreading could have been empty. The key part in the error message is "must be passed to a rest parameter", and from the various overload signatures the one you'd want to use is assign(target: object, ...sources: any[]): any;. To avoid the need for // @ts-ignore, you'd write

    return Object.assign({}, ...keyArr.map((el,index) => ({[el]: valueArr[index]})))
    //                   ^^^
    

    (Playground demo)

    However, you really should not use Object.assign for this. What you want is Object.fromEntries, which takes an iterable of tuples:

    export default function getObjectFromTwoArrays(keyArr: Array<any>, valueArr: Array<any>) {
      if (keyArr.length === valueArr.length) {
        return Object.fromEntries(keyArr.map((key, index) => [key, valueArr[index]]))
      } else {
        throw new Error(`Arrays should be the same length: ${{keyArr}}, ${{valueArr}}`)
      }
    }