microsoft / microsoft/TypeScript
Allow generic yield* types
Abierto
@rbuckton ya está trabajando en esto.
Desde el 23/11/2020.
Effort: Moderate
Help Wanted
Rescheduled
Suggestion
- Lenguaje dominante
- Go
- Estrellas
- 111k
- Forks
- 14.4k
- Merge medio
- 1 d 19 h
- PR fusionados (30 d)
- 117
Descripción
Search Terms
generic yield asterisk type preserve
Suggestion
Currently, the yield* construct doesn't work properly with generic types. I would like to see these kinds of situations get proper types:
function* foo<T extends Iterable<any>>(x: T) {
yield* x;
}
// Inferred return type: `Generator<any, void, undefined>`
I would like to see some kind of Iteratorify types added:
type YieldTypeOfIterableType<R> = R extends Iterable<infer Y> | Iterator<infer Y> | IterableIterator<infer Y> | Generator<infer Y> ? Y : never;
type Awaited<T> =
T extends null | undefined ? T : // for non-strictNullChecks
T extends PromiseLike<infer U> ? Awaited<U> :
T;
/** Extracts the `Symbol.asyncIterator` return type, falling back to the `Symbol.iterator` return type if necessary. */
type AsyncIteratorify<T> = [T] extends [{ [Symbol.asyncIterator]: () => void } | { [Symbol.iterator]: () => void }]
// Tests whether a given type has a valid AsyncIterator / Iterator in every unioned type before actually computing the type
// This is so AsyncIteratorify<Set<string> | {}> will resolve to `never`
? T extends infer U
? U extends { [Symbol.asyncIterator]: () => infer R }
? YieldTypeOfIterableType<R>
: U extends { [Symbol.iterator]: () => infer R }
? Awaited<YieldTypeOfIterableType<R>>
: never
: never
: never;
/** Extracts the `Symbol.iterator` return type. */
type Iteratorify<T> = [T] extends [{ [Symbol.iterator]: () => void }]
// Tests whether a given type has a valid Iterator in every unioned type before actually computing the type
// This is so Iteratorify<Set<string> | {}> will resolve to `never`
? T extends infer U
? U extends { [Symbol.iterator]: () => infer R }
? YieldTypeOfIterableType<R>
: never
: never
: never;
function foo<T extends Iterable<any>>(arr: T): Generator<Iteratorify<T>>;
function* foo<T extends Iterable<any>>(x: T) {
yield* x;
}
for (const x of foo([1, 2])) console.log(x); // x is a number :D
However, this still won't work for generic this parameters in Symbol.iterator calls:
for (const x of foo({
a: 1,
*[Symbol.iterator]<T>(this: T) {
for (const x in this) yield x;
}
})) console.log(x);
For this, we would need https://github.com/microsoft/TypeScript/issues/37181 (and we would need a way to allow for passing in implicit this parameters in that proposal)
Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
- This feature would agree with the rest of TypeScript's Design Goals.
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Evaluación
Este issue todavía no se ha evaluado.