javascript - Varför får jag hela tiden TypeScript-felet "No overload matches this call" när jag använder Array concat?


Jag har skrivit en funktion för att få de första n elementen från en array:

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

Här är länken till skriptet för att reproducera.

Kompilatorn returnerar ett fel

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()

När jag kollar på lib.es5.d.ts-filen med VSCode, accepterar concat två överlagrade parametrar.

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

Genom att se den andra typen av anrop har jag försökt ändra den första parametern i first-funktionen från array: T[] till array: (T | ConcatArray<T>)[], men då returnerar det ett fel,

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>'

Vad ska jag göra för att åtgärda de där felen? Jag är ny på TypeScript, så ha överseende om det här är en dum fråga.

Svar #1

I detta GitHub-ärende kan du se varför arrayen har typen never, det huvudsakliga svaret är:

Detta orsakas av kombinationen av strict och noImplicitAny: false. Generellt förväntar vi oss att om strict är på, är noImplicitAny också på; denna särskilda uppsättning av inställningar kommer att avslöja något udda beteende. Om du hade båda på, skulle du se ett fel om att [] implicit är any[]; om båda var avstängda, skulle vi använda kontrollflödesanalys och behandla arrayen som en number[] efter push(1);.

Den specifika kombinationen av inställningar innebär att vi inte tillåter oss att använda kontrollflödesanalys eller tillåta arrayen att implicit vara any[], så never[] är det enda återstående tillåtna alternativet.

Jag skulle rekommendera att stänga av strict om du inte ska ha noImplicitAny på.

När det gäller hur du kan lösa ditt problem kan du använda någon av de två metoder jag skriver i detta TS-lekplats, jag rekommenderar dig den andra eftersom du där kommer att ta hänsyn till de två möjliga värdena som funktionen returnerar, i den första fuskar du bara TS med typkonverteringen för att returnera T[], men troligtvis kommer typen att vara undefined när arrayen inte har ett värde.

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

  return [array.shift()]
}

Relaterade artiklar