Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I keep getting TypeScript error "No overload matches this call" when using Array concat?

I've written a function to get first n items from an array:

export const first = <T>(array: T[], n?: number): T[] => {
  if (n) return array.slice(0, n)
  return [].concat(array).shift()
}

Here is the link of the script to reproduce.

The compiler returns an error

error TS2769: No overload matches this call.
      Overload 1 of 2, '(...items: ConcatArray<never>[]): never[]', gave the following error.
        Argument of type 'T[]' is not assignable to parameter of type 'ConcatArray<never>'.
          The types returned by 'slice(...)' are incompatible between these types.
            Type 'T[]' is not assignable to type 'never[]'.
              Type 'T' is not assignable to type 'never'.
      Overload 2 of 2, '(...items: ConcatArray<never>[]): never[]', gave the following error.
        Argument of type 'T[]' is not assignable to parameter of type 'ConcatArray<never>'.

   return [].concat(array).shift()

When I check lib.es5.d.ts file with VSCode, concat accepts two overloading parameters.

concat(...items: ConcatArray<T>[]): T[];
concat(...items: (T | ConcatArray<T>)[]): T[];

By seeing the second type of call, I've tried to change the first parameter of first function from array: T[] to array: (T | ConcatArray<T>)[] but then it returns error,

Overload 2 of 2, '(...items: ConcatArray<never>[]): never[]', gave the following error.
    Argument of type '(T | ConcatArray<T>)[]' is not assignable to parameter of type 'ConcatArray<never>'

What should I do to fix those errors? I'm new to TypeScript so pardon me if this is a dumb question.

like image 473
Learn Avatar asked Oct 20 '25 03:10

Learn


1 Answers

In this github issue you can see why the array have a never type,the principal response is:

This is caused by the combination of strict and noImplicitAny: false. In general we expect that if strict is on, noImplicitAny is also on; this particular set of settings will expose some odd behavior. If you had both on, you'd see an error about the [] being implicitly any[]; if both were off; we'd use control flow analysis and treat the array as a number[] after the push(1);.

The particular combination of settings means that we don't allow ourselves to use control flow analysis or allow the array to be implicitly any[], so never[] is the only remaining allowable option.

I'd recommend turning off strict if you're not going to have noImplicitAny on.

respect to how to fix your problem, you can use any of the two approaches I write in this TS playground, I recommend you the second because there you will take in account the two possible values returned by the function, in the first you just cheat TS with the type assertion to return T[], but probably the type will be undefined when the array doesn't have a value.

const second = <T>(array: T[], n?: number): (T | undefined)[] => {
  if (n) return array.slice(0, 2)

  return [array.shift()]
}
like image 120
Oscar Velandia Avatar answered Oct 21 '25 17:10

Oscar Velandia



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!