Repository navigation
Open
Labels
Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScriptAn idea for TypeScript
Description
Search Terms
- generator
- iterator
Suggestion
Express a fixed-length generator.
Use Cases
- Allows the spread syntax on functions to know how many arguments is deconstructed (see examples below)
Examples
// Vector2.ts
class Vector2 {
constructor (public x, public y) {
this.x = x;
this.y = y;
}
//... A bunch of vector methods
public* [Symbol.iterator]: Generator<number, void, unknown> {
yield this.x;
yield this.y;
}
}
// main.js
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
const a = new Vector2(0, 0);
const b = new Vector2(10, 10);
ctx.beginPath();
ctx.moveTo(...a);
// works correctly, but with this warning:
// Expected 2 arguments, but got 0 or more.ts(2556)
ctx.lineTo(...b);
ctx.stroke();
ctx.closePath();Right now, the code above produces the correct behavior. However, typescript doesn't not recognize how many arguments is passed to ctx.moveTo and ctx.lineTo therefore it warns me about it.
My Implementation
There could be an tuple-like syntax for generators as well, for example:
public* [Symbol.iterator]: *[number, number] {
yield this.x;
yield this.y;
}With this syntax, typescript recognizes how many argument is deconstructed by the spread operator, and knows its a generator with the prepending *.
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.
Reacted by Trey Brisbane, Harry Solovay, EL AYADI Mohamed, Alec Larson, Jeff Zou, Wessel Kronemeijer, Josiah Nunemaker, MHebes, Anton Mikhailov, Taj Pereira and 27 more
Reacted by Joe Calzaretta, Jesse Jackson, Taj Pereira, Aadit M Shah, Utku, Daryl Zuniga and Alvaro Bernar Silos
Metadata
Metadata
Assignees
Labels
Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScriptAn idea for TypeScript
Activity
treybrisbane commentedon Dec 30, 2020
Wow, I just came here to raise this, only to find this issue created only a couple weeks ago! Crazy timing! 😮
In any case, the use-cases presented in #32523 also require (or rather, are partially enabled by) this feature. Specifically, those use-cases are:
redux-saga's Sagasmobx-state-tree's Asynchronous Actionsdosyntax for sequencing monadic actions (example)treybrisbane commentedon Dec 30, 2020
Thinking a bit about type inference...
I imagine it would be straightforward for simple cases, right?
For example, the inferred return type of
would presumably be either
*[0, 1]or*[number, number](to borrow SIGUSR97's syntax).As soon as loops are involved though, it looks like things get much more fun! 😅
For example, what would the inferred return type of
be?
I'm guessing something like
*number[]?Let's get more complex though. What would the inferred return type of
be?
Maybe something like
*[0, ...*number[], 4]or*[number, ...*number[], number]?When you start thinking about nested loops, things look a bit scary. Generics and conditionals further terrify me. 😱
treybrisbane commentedon Dec 30, 2020
Ron Buckton (@rbuckton) You seem to be Generator Man; got any thoughts on this? 😜
aleclarson commentedon Jul 8, 2023
Can we get an official comment explaining why this isn't higher priority? I want to destructure a class instance as if it was a tuple. I define
0and1getters on the prototype and both have different type signatures.thehappycheese commentedon Jun 22, 2024
Arrived here with the exact same use-case and issue as Jeff Zou (@zojize); vector types and the canvas.
Feels like I should be able to manually specify something like
TupleGenerator<[number, number], ...>It could de-sugar to something like below;Static type inference for
*[Symbol.iterator]is obviously impossible for complex iterators... but why not have this for manually specified types :)zojize commentedon Aug 14, 2024
thehappycheese I submitted a PR based on your suggestion, let me know what you think 😃
FrameMuse commentedon Sep 29, 2024
Have the same need, my case is very specific and it some might not like this, but I believe this is very handy.
Consider any state in modern frameworks, they usually like
[get, set] = stateor{ get, set } = state. What I want is to provide isomorphic structure that supports both but only on demand. I don't want to create an array when it's not relevant and I don't want developers to see array methods exposed as well as they are not relevant.Currently, when I try to destruct as array, the types are not correct.
iliaamiri commentedon Oct 5, 2024
My use-case is that I want to create a minimal array that only has the tuple values and no other methods such as:
map,flatMap,forEach, etc.Let's say I created an object and artificially implemented the
[Symbol.iterator]()method myself.When I destructure it, I get a union type:
The nice thing about my

CustomTupleis that, I don't see the extra Array API that comes with a regular Array object:So the user cannot do
tuple[0]ortuple[1]either. That's what I want.So, there is no way I can achieve the same result as defining a standard fixed tuple:
runspired commentedon Aug 18, 2025
It was mentioned to me that folks didn't think polymorphic/megamorphic generators are commonly in use and perhaps this is why TS has not focused on improving the types here, but they are. Multiple popular libraries use only megamorphic signatures while encouraging either compilation or use of
anyto paper over the limitations of using generators.The transpiler route: these libraries compile async/await in the bodies of specially marked functions into generator functions with yield in order to enable proper typing.
The nothing-to-see-here route: these libraries have the same limitation but won't tell you that in their docs while showing you nice examples. They presume you're ok with a lot of
anyandneverin your types or will just write JS and not care about the types.This said, I suspect the underlying JS spec for generators and iterators makes it exceedingly hard/probably impossible to create a linkedlist or well-known-series structure that works both for typing the function* body and for typing the produced generator/iterator since TS can't shorten the list each time next is called.
FrameMuse commentedon Aug 18, 2025
Chris Thoburn (@runspired) Yep, it seems like that
I'm not into how TS is implemented, but if it can track deep nested types and do some operations that require states, probably this could be implemented as well.