Incorrect inferred function return type with destructuring assignments

Ouverte
#56,771 5 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Évaluation

Difficulté
4/5
Temps estimé
3-5 jours
Accessibilité débutants
35/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
À l'abandon
Stack technique
typescript
Domaine
compilers

Piste de recherche

Commencez par le repro fourni dans TypeScript Playground et comparez les cas 1–4, en vous concentrant sur l’inférence des types de retour génériques au travers d’affectations par déstructuration. Suivez la raison pour laquelle le cas 4 élargit le résultat à R, puis vérifiez que A3.a ne signale plus d’erreur liée à null ou undefined, tandis que les autres cas restent inchangés.

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

Description

Bug Domain: check: Type Inference Help Wanted
🔎 Search Terms

"return type destructure"
"destructuring assignment type"

🕗 Version & Regression Information
  • This changed between versions 3.3.3 and 3.5.1
⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.3.2#code/C4TwDgpgBASlC8UDeAoK6oEEBcy0YIENcByTE-dAXygB8oA7AVwBsW6omGATCAMwCWDCNxRUUfLgGNgAgPYMofBgB4AKlAgAPYBB4BnWAD4AFMGxqAlLg14CAJwjAm9xUhqFDagNxiUKAHoAKhQASUUIQikACyhdfWAoKU9oACMIFjkAdwAaKFCSbihPfSYAW2hgaOhHZ1c48Gg5PiVpWQU4uSh0qAADJBxkYigyEioqXoA6FAAJbIgANwh7POT9aAAWTnXDXgT7JhkXIQBzYp446IFDQjBIQntDYC7ePkJWRKqapxdFUEhOn0YFMUEEAv4AgEoABhFJQACMgSh0Lk9kcMhYICgQj4yyejSgzT6jlKLGAk0wvWKhn6gyQw1G416KCkCgSUBJHwQSgYJgGuHppHI40svk5ZIpk0I3igkKgADkust7KiIci4QAmJEw1Ho4CY7EMXGPBoAomYeHUvqCkbC5mshjsi3c5R8ukM4VUSwU3wWqUyuWKzRo1Xa2HrKAAZjDuogGKxOLxpqaLUwkat-Q9Y3tbMS-KwGpoiFd+ZtjI8hgdCVFKEwGv9sqhQeVobl4c22vCrLRcf1CaNSf+KYLGdLWZo9GYbA4XFeQhEExZueQgzTRZ5boF469vsjDblAFEQ-ZcAB5VIAK172MMYDk+n0AlSBt6U5YVNRfVn-Hn3F6QA

💻 Code
type R = {
    A: {
        a: 'A'
    } | null | undefined
}
function fn<T extends R>(t:T): T  {
    return {} as T;
}

/*
In each test case below, I'd assume the return type of function to be `{A: {a: 'A'}}`.
However, case 4 uses destructuring and this appears to default the return type to `R`.
*/

// Case 1
// Correctly infers type of `result.A` as `{A: {a: 'A'}}`
const result = fn({A: {a: 'A'}});
result.A.a; // No error

// Case 2
// Correctly infers type of A1 as `{a: 'A'}`
const A1 = fn({A: {a: 'A'}}).A;
A1.a; // No error

// Case 3
// Correctly infers type of A3 as `{a: 'A'}`
const {A: A2} = fn({A: {a: 'A'}} as const);
A2.a; // No error

// Case 4
// Incorrectly infers type of A2 as `{A: {a: 'A'} | null | undefined}`
const {A: A3} = fn({A: {a: 'A'}});
A3.a; // Error: Object is possibly `null` or `undefined`
🙁 Actual behavior

In case 4, accessing A3.a results in error "Object is possibly null or undefined".

Appears that the inferred type of A3 is {a: 'A'} | null | undefined. I suspect when we destructure, the return type of fn is inferred as R instead of the narrowed generic type variable T.

🙂 Expected behavior

Expect no errors. Should be able to access A3.a, similar cases 1, 2, and 3. Expectation is that destructuring assignment shouldn't modify inferred return type of function.

Additional information about the issue

Current workarounds:

  • Use as const appended to param (see case 3)
  • Use const with generic type variable in function signature (function fn<const T extends R>(t: T): T;)
  • Avoid destructuring assignments (case 1 & 2)
Langage dominant
Go
Étoiles
111k
Forks
14.4k
Merge moyen
1 j 19 h
PR mergées (30 j)
117

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.

Autres issues de microsoft/TypeScript

Toutes les issues de microsoft/TypeScript

Issues similaires

Plus d'issues Go

Recevez les nouvelles issues par e-mail

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