No overload matches this call in TypeScript when concatenating arrays of different signatures

I am getting this error:

No overload matches this call.
  Overload 1 of 2, '(...items: ConcatArray<{ title: string; width: number; dataIndex: string; render: (level: string) => Element; }>[]): { title: string; width: number; dataIndex: string; render: (level: string) => Element; }[]', gave the following error.
    Argument of type '{ title: Element; dataIndex: string; width: number; render: (myThing: MyType) => Element; }[]' is not assignable to parameter of type 'ConcatArray<{ title: string; width: number; dataIndex: string; render: (level: string) => Element; }>'.
      The types returned by 'slice(...)' are incompatible between these types.
        Type '{ title: Element; dataIndex: string; width: number; render: (myThing: MyType) => Element; }[]' is not assignable to type '{ title: string; width: number; dataIndex: string; render: (level: string) => Element; }[]'.
          Type '{ title: JSX.Element; dataIndex: string; width: number; render: (myThing: MyType) => JSX.Element; }' is not assignable to type '{ title: string; width: number; dataIndex: string; render: (level: string) => JSX.Element; }'.
            Types of property 'title' are incompatible.
              Type 'Element' is not assignable to type 'string'.
  Overload 2 of 2, '(...items: ({ title: string; width: number; dataIndex: string; render: (level: string) => Element; } | ConcatArray<{ title: string; width: number; dataIndex: string; render: (level: string) => Element; }>)[]): { ...; }[]', gave the following error.
    Argument of type '{ title: Element; dataIndex: string; width: number; render: (myThing: MyType) => Element; }[]' is not assignable to parameter of type '{ title: string; width: number; dataIndex: string; render: (level: string) => Element; } | ConcatArray<{ title: string; width: number; dataIndex: string; render: (level: string) => Element; }>'.
      Type '{ title: Element; dataIndex: string; width: number; render: (myThing: MyType) => Element; }[]' is not assignable to type 'ConcatArray<{ title: string; width: number; dataIndex: string; render: (level: string) => Element; }>'.

The error is because I am concatenating two arrays, with different signatures:

const columnA = {
  title: '',
  width: 100,
  dataIndex: 'level',
  render: (level: string) => {
    return <b>L{level}</b>
  }
}

const remainingColumns = [
  {
    title: (
      <div>hello</div>
    ),
    dataIndex: 'something',
    width: 240,
    render: (myThing: MyType) => {
      return <div>{myThing.title}</div>
    }
  },
  {
    title: (
      <div>world</div>
    ),
    dataIndex: 'else',
    width: 240,
    render: (myThing: MyType) => {
      return <div>{myThing.title}</div>
    }
  }
]

const columns = [columnA].concat(remainingColumns)

How do I resolve this, I have a dynamic number of remainingColumns all which have signature 1, and then the 1 columnA which has signature 2.


You can use array spread notation:

const columns = [columnA, ...remainingColumns]

The type will be inferred as an array where the component type is a union, which is presumably what you want:

const columns: ({
    title: Element;
    dataIndex: string;
    width: number;
    render: (myThing: MyType) => Element;
} | {
    title: string;
    width: number;
    dataIndex: string;
    render: (level: string) => Element;
})[]

There is also no need to worry about compatibility with older versions of Javascript; if you set the output language as ES5, for example, then Typescript will translate the spread syntax to equivalent ES5 code.