microsoft / microsoft/TypeScript

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

Abierto
#54,551 1 comentario 1 reacción 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Domain: lib.d.ts Possible Improvement
Lenguaje dominante
Go
Estrellas
111k
Forks
14.4k
Merge medio
1 d 19 h
PR fusionados (30 d)
117

Descripción

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

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza con la definición de Promise.prototype.then en src/lib/es5.d.ts alrededor de la línea 1524 y reproduce el ejemplo proporcionado del playground. Comprueba cómo están tipadas las formas de uno y dos argumentos, y determina si la cuestión de tipado contextual de nullish-operator debe tratarse por separado. Se considera terminado cuando se haya verificado el tipo previsto de la forma de un argumento sin introducir regresiones en el comportamiento documentado de Promise.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
javascript, typescript
Área
compilers
Tipo de issue
Error
Dificultad
3/5
Tiempo estimado
1-2 días
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
35/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.