microsoft / microsoft/TypeScript

Type inference lost after spreading array with `ArrayLike`

Ouverte
#58,286 2 commentaires 1 réaction 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Domain: check: Type Inference Help Wanted Possible Improvement
Langage dominant
Go
Étoiles
111k
Forks
14.4k
Merge moyen
1 j 19 h
PR mergées (30 j)
117

Description

🔎 Search Terms

array inference, type inference, ArrayLike, lodash compact, _.compact

🕗 Version & Regression Information
  • This changed between versions 4.9.5 and 5.0.4
⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.0.4#code/C4TwDgpgBAsiAq4IB55QgD2BAdgEwGcoBXHAaxwHsB3HAPigF4oBvAKCigFsQBpCEAC4o8ANwduIAGKkAxsACWlHMIAUAQwBOAcwCMw+AEomDAG6UFecQF9xbWcoLAo23BE3rsTKKsPCAgpoeIMhwiJDITpoKONp0DIwM7JyaEMDEmjhQgcEAdABmmpRcqixQADa42sAAFsIArFDWhrlc6mChCEiRwNGx8aqqAPoANFAxeJjGiawSKWkZWcmcKzz8QlAABgAkLBOY1psjc6vScorKalp600knK1Cp6ZniD5zWxw+2Es02dg44JxQLTBAAyCjIEAAkjh8u5cLIIDIcPIlFlmKh0FhcIQSOQqLQ6KoJCCAkF1CBwZDMQAfKA4YjlcpQOmkSb5GIQPAsqD5dTlAjQOkAImFPIADAw6QymTy2RAOTguWw-CIANoAXRMs3mzyymr+bHsjmcIIpVOhsPcqRR0GYZspEMtcJtiORqOUqjVEjKawEwmFugATABmYVjHjui4qHymfnECC3VjWJqfKC9BNQABkWdYknWAYALPUAGzhyRRtFqOPlBNJlgpj4SPkC6A5vN+jbC4tliNnFHR6vxxPahupiS5SeuJUebC+NMAegX6aQ4ytQQgiKglHyFfOaPGRHKlCcEgzbdzvr4-qg3dL5cj+8useH9cbaZbguzl-zN7vvb3AcqxfWsRxmMcm04K8C1vHsH37D0Y1UGs61Hd82A1Qx-hNYFyRAGEXQRJEn3RKBMUwbB8CIUgKBoehiU4Ulsjw2l6UZZlWXwBVOW5OlPyFW8xTpSUeRlDi8XZHiVQMTVRwkJ5FigA02G+Y1AVNPCCPhW1vAdLTXWIoDPW9KDfy7YMwz7Stn2Q180PHThz2-Dtry7OCrJIodQLfBzeX5L922gv93MAxCvNQ8D0M4SdcmndxPAgecJCXFdIDXF1Ui3HdQujQ8oEhMBgDPTRM0Csyi3vDyjKQlCwKSKK-NbZygrcyqcuA2zvPsyCXJg-94Osmq7Mi8dMPEIA

💻 Code
type MyType<T extends unknown> = {
  myKey: T;
  myFunction: (arg1: T) => void;
};

const generate = (): Array<MyType<string>> => {
  return Array.from({ length: 5 }).map<MyType<string>>((_, index) => {
    return {
      myKey: `${index}`,
      myFunction: (arg1) => {
        return;
      },
    };
  });
};

const arrayLikeInferenceFunction = <T extends unknown>(
  arr: ArrayLike<T | null | undefined | false | "" | 0> | null | undefined
): T[] => {
  return [];
};

const arrayLikeInference = arrayLikeInferenceFunction([
  { myKey: "123", myFunction: (value) => {} }, // value is correctly inferred as string
  true && { myKey: "456", myFunction: (value) => {} },
  false && { myKey: "456", myFunction: (value) => {} },
  ...generate(),
  // type inference of myFunction is lost
  true && { myKey: "456", myFunction: (value) => {} }, // value is inferred as any
  false && { myKey: "456", myFunction: (value) => {} },
  { myKey: "456", myFunction: (value) => {} },
]);

const arrayInferenceFunction = <T extends unknown>(
  arr: Array<T | null | undefined | false | "" | 0> | null | undefined
): T[] => {
  return [];
};

const arrayInference = arrayInferenceFunction([
  { myKey: "123", myFunction: (value) => {} }, // value is correctly inferred as string
  true && { myKey: "456", myFunction: (value) => {} },
  false && { myKey: "456", myFunction: (value) => {} },
  ...generate(),
  // type inference of myFunction is kept
  true && { myKey: "456", myFunction: (value) => {} }, // value is correctly inferred as string
  false && { myKey: "456", myFunction: (value) => {} },
  { myKey: "456", myFunction: (value) => {} },
]);
🙁 Actual behavior

The typings of the arguments of myFunction are lost after the array spread when using ArrayLike. When using Array, the type inference is kept.

🙂 Expected behavior

The arguments of myFunction should be inferred as string

Additional information about the issue

I have opened a similar issue in the DefinitelyTyped repository for the lodash typings and they suggested opening an issue in this repository. https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/69410

The issue originated from using lodash.compact() with code similar to the code below:

import _ from "lodash";

type MyType<T extends unknown> = {
  myKey: T;
  myFunction: (arg1: T) => void;
};

const generate = (): Array<MyType<string>> => {
  return Array.from({ length: 5 }).map<MyType<string>>((_, index) => {
    return {
      myKey: `${index}`,
      myFunction: (arg1) => {
        return;
      },
    };
  });
};

const lodashInferred = _.compact([
  { myKey: "123", myFunction: (value) => {} }, // infers value as string
  true && { myKey: "456", myFunction: (value) => {} },
  false && { myKey: "456", myFunction: (value) => {} },
  ...generate(),
  { myKey: "123", myFunction: (value) => {} },  // infers value as any
  true && { myKey: "456", myFunction: (value) => {} },
  false && { myKey: "456", myFunction: (value) => {} },
]);

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par la reproduction liée dans Playground avec TypeScript 5.0.4 et comparez les cas ArrayLike et Array autour du spread de generate(). Suivez le comportement de l’inférence des types pour les paramètres du callback ; c’est terminé lorsque les arguments de myFunction sont inférés comme string après le spread de ArrayLike, avec la régression signalée couverte par un test.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
typescript
Domaine
compilers
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.