microsoft / microsoft/TypeScript

`.then(onresolved)`'s return type should not be inferred from contextual type

Ouverte
#54,551 1 commentaire 1 réaction 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Domain: lib.d.ts Possible Improvement
Langage dominant
Go
Étoiles
111k
Forks
14.4k
Merge moyen
1 j 19 h
PR mergées (30 j)
117

Description

lib Update Request

Configuration Check

My compilation target is ES2015 and my lib is the default.

Also reproducible with target ESNext, ES2022 ect.

Missing / Incorrect Definition

Promise.prototype.then

Sample Code

TypeScript infers the return type of then from the contextual type information when called with only one argument.
This can cause unexpected results

let a: string | undefined
const b = a ?? await somePromise.then(() => "str")

I expect b to be string because either a is a string, somePromise resolves and then returns a string, or somePromise rejects and await throws so b is not assigned.
However b is actually string | undefined because the contextual type on the RHS of a nullish operator is the type of the LHS
and then inferred it's return type from the context because TResult2 was not inferred from arguments.

b satisfies string | undefined

I think there's actually two issues here

  • The contextual type of the RHS of nullish operator is the type of the LHS
  • .then's type definition does not use overloads for different number of arguments

The first issue seems debatable, I can understand the current behavior but these alternates make sense as well

  1. The contextual type of R should be unknown or the same as the whole L ?? R expression
  2. The contextual type of R should be NonNullable<L>

Let me know if this should be a separate issue or if there is interesting reading on the current behavior.

The next issue is caused because the return type of .then is Promise<TResult1 | TResult2> and TResult2 is not inferred from then's arguments when onrejected is not provided so it's inferred from the contextual type.

I think this issue can be fixed by changing the library to use overrides

then<TResult1>(onresolved: (t: T) => TResult1): Promise<TResult1>
then<TResult1, TResult2>(onresolved: (t: T) => TResult1, onrejected: (err: any) => TResult2): Promise<TResult1 | TResult2>
// more overrides for 0 or only onrejected args.

Documentation Link

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
https://github.com/microsoft/TypeScript/blob/main/src/lib/es5.d.ts#L1524

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 définition de Promise.prototype.then dans src/lib/es5.d.ts vers la ligne 1524 et reproduisez l’exemple fourni du playground. Vérifiez comment sont typées les formes à un et deux arguments, et déterminez si le problème de typage contextuel de nullish-operator doit être traité séparément. Le travail est considéré comme terminé lorsque le type attendu de la forme à un argument est vérifié sans régression du comportement documenté de Promise.

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

Évaluation

Stack technique
javascript, typescript
Domaine
compilers
Type d'issue
Bug
Difficulté
3/5
Temps estimé
1-2 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.