MDN establece que los iteradores asíncronos tienen un método de retorno
const asyncIterable = { [Symbol.asyncIterator]() { let i = 0; return { next() { const done = i === LIMIT; const value = done ? undefined : i++; return Promise.resolve({ value, done }); }, return() { // This will be reached if the consumer called 'break' or 'return' early in the loop. return { done: true }; } }; } }; Sin embargo, las definiciones de TypeScript de los iteradores asíncronos requieren el método de return para
{value: someValue, done: true} , mientras que MDN no hace esto.Aquí está la definición de TS:
interface AsyncIterator<T, TReturn = any, TNext = undefined> { // NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places. next(...args: [] | [TNext]): Promise<IteratorResult<T, TReturn>>; return?(value?: TReturn | PromiseLike<TReturn>): Promise<IteratorResult<T, TReturn>>; throw?(e?: any): Promise<IteratorResult<T, TReturn>>; } ¿Alguien puede explicar la discrepancia? ¿Cómo funciona la return ?
MDN, a pesar de su autoridad, no es la fuente de la verdad cuando se trata de especificaciones de lenguaje. TypeScript sigue la especificación ECMAScript , en este caso, la definición de la interfaz AsyncIterator (como el símbolo conocido @@asyncIterator es un método que devuelve un AsyncIterator ).
Las tablas 76 y 77 de la especificación proporcionan, respectivamente, las propiedades obligatorias y opcionales de la interfaz: next , return y throw . Estamos interesados en lo que dice la especificación sobre los parámetros del segundo:
La promesa devuelta se cumplirá con un objeto
IteratorResultque normalmente tendrá una propiedad "hecha" cuyo valor es verdadero y una propiedad "valor" con el valor pasado como argumento del método de devolución. Sin embargo, este requisito no se cumple.
Tenga en cuenta la última parte de la primera oración: aquí es donde TReturn | PromiseLike<TReturn> Procede de TReturn | PromiseLike<TReturn> . Luego, tenga en cuenta la segunda oración: esta es la razón por la cual el parámetro es opcional.
Como también puede ver en lo anterior, el método de return devuelve un objeto que implementa la interfaz IteratorResult que se define para tener una propiedad booleana done y una propiedad de value sin restricciones. Ambas propiedades no se consideran opcionales, pero cada una tiene una nota en la tabla 78 de la especificación que permite que falten.
Sin embargo, la definición de TypeScript para IteratorReturnResult (un miembro del tipo de unión IteratorResult ) no tiene en cuenta esas notas y marca esas propiedades como necesarias:
interface IteratorReturnResult<TReturn> { done: true; value: TReturn; }Esto ha sido cuestionado en el problema #8938 en el repositorio fuente con el razonamiento del equipo:
Como señaló @ivogabe, necesitamos tener tipos literales booleanos para poder modelar este con precisión.
y posteriormente se cerró a favor del número 2983 arreglado por el PR n.° 30790 con la solicitud original aparentemente deslizándose por las grietas.