-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
update typings to indicate Seq()
faux-iterator support
#1886
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
update typings to indicate Seq()
faux-iterator support
#1886
Conversation
…property named `@@iterator` (e.g. for environments pre-ES2015 where `Symbol.iterator` does not natively exist). Related discussion on pull request immutable-js#1589
Looks pretty straightforward to me. |
I'd rather avoid this change's approach and leverage one where ES5 environments use their own definition of Even if we did go for this approach, this change is too limited, there are well over 100 references to See my comment on the PR in concern for thoughts on another approach |
The In general, isn't it best for Your suggestion should work, but it would be lying about The helpful declarations you provide in the PR comment are technically specific to ImmutabjeJS. Shouldn't all library-specific declarations be somewhere in |
I was about to say something similar actually. Changing the libdefs would affect the language and all other libraries. It's the kind of thing that would make me swear very loudly if I discovered someone else had done it in a codebase I had to work in. It shouldn't be that hard to update the definition of Iterable across all the |
Standing in the shoes of a user it would be much appreciated if we didn't conflate the faux iterable and the real one into a single type named If everywhere If a single type name is preferred, could we perhaps use something along the lines of Thoughts? |
I definitely see your point, but also you're in the minority here. Most users will be in an environment in which they can use iterables, and it isn't going to be clear to them what |
Understood. As you say, a good IDE should be able to easily expand Doesn't that make it clear that Seq() can take either an I would naturally expect Maybe I'm misunderstanding but trouble with the single name Another option is to just remove the current fake iterator support from In any case (recognizing I'm in the minority), anything y'all can do to resolve this would be acceptable and appreciated! |
After reviewing by babbling above, since a ES5 environment would not have any It would also save me from changing my |
My priorities are
1. Make it works correctly and continues to work correctly for everyone.
2. Make sure it gives pretty errors in common cases.
In my mind distributing the union across all the usages is a no-go because it's hard to maintain. Likely future editors will forget to do it and reviewers will fail to notice and then you'll end up with subtle type bugs. If we support this we should support it well, i.e. in a single place where it can have comments and where we can easily pull it out eventually when it's no longer needed.
|
Agreed, if the Immutable declaration for |
Sounds great to me! If you're going to implement it that way just remember that you have to make a separate file to convert from a global name to an export, but that's the only thing that needs to go in that file. Here's an example from some recent work I did: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/d2c1186142999c17273b075a8ddf97ea9e830983/types/error-cause/base/Error.d.ts |
Not specific to Immutable! The To a degree this is Immutable showing its age. It needed to support iteration protocols in both older and modern browsers, and that's why this
Ideally the type definitions should not care that there are two different execution environments with two different ways of defining the iterator property. I think we should discourage actively mixing the two, since not all other libraries have this broad support and that could lead to confusing errors. That's why my initial advice was to define the version of
Yeah this is a very good point and one I suspect you'll need to be practical about based on the situation you're in. It's exactly the reason why Immutable doesn't try to define these well defined types itself (it used to pre-v4!). If you have a very large codebase with many libraries that also have a conception of what
This could work for you, but remember that |
Ah that's great context. I didn't know I agree that that's a pain, but also just for fun I went to check on the implementation of |
The issue here was the difference between the ES spec (which is reflected in the TypeScript bundled lib definition for Succinctly, Lee, if the decision is yours, would you kindly confirm that Immutable will not be updating the type definitions to include the full range of acceptable inputs to At least with that cemented I can know whether I'll be able to use 4.x, or be forced to stick with 3.8 forever or choose another library entirely. |
I'll say one last thing: immutable is in no small part a legacy library. It does some pretty incredible things given that it also works in some pretty barebones environments. At some point though I think it should transition from being an es3 library to being an es6 library, and the 4.0 release is an ideal point to make that pivot. The API has been feature-stable for a long time, and 4.0 was largely a polish release getting rid of most known flaws in the implementation. What I'm saying is that I don't think we have to try to bury the idiosyncrasies of 4.x, because they're not long term. We want the people who care about beautiful design and integration to adopt 5.x, which of course we haven't even begun writing. |
Yes this plus my agreement with your previous point about
The case I was trying to make before is that this is exactly material. It wasn't that Immutable.js wanted some custom faux iterable implementation and happened to choose Your case of having an ES5 environment to support is exactly the reason why this behavior exists in Immutable.
Very reasonable concern if this was an Immutable.js's definition of an iterator! Since they only exist to support older environments, the only reason we'd ever change them is if we decided to drop support for pre-ES6 browsers, and that would come with a major version change.
Totally agree. Runtime behavior is supporting ES5 correctly, so this is a purely a matter of supplying the correct TypeScript types. Maybe this seems like a subtle difference, but I think it's actually quite important to get right - Also note that Immutable's typedefs are not specifically using the ES6 Iterable type lib. It just expects that you'll have have a TypeScript environment that has this type defined. Since there is a specification for them in ES6, TypeScript supplies that typelib directly for you to include in your environment via My recommendation stands that since TypeScript does not offer this directly, you can provide one yourself. Luckily it is a really small lib to write. lib.es5.iterable.d.tsinterface Iterator<T> {
next(): { done: boolean, value: T };
}
interface Iterable<T> {
['@@iterable'](): Iterator<T>;
}
interface IterableIterator<T> extends Iterator<T> {
['@@iterable'](): IterableIterator<T>;
}
interface Array<T> {
['@@iterable'](): IterableIterator<T>;
}
interface ReadonlyArray<T> {
['@@iterable'](): IterableIterator<T>;
}
Since Immutable.js's type defs expect I don't think it would be the right thing to do to have Immutable.js directly define the ES5 Iterables type. Especially since that would impact the |
While directly including ES5 iterators this in the immutable.d.ts file could have breaking changes to the environment, I could still be reasonable to offer this somewhere easy for people to import? |
@ShawnTalbert Does your environment define |
Nay, there is no |
Right. So I think that means I'm settled in disagreement with @leebyron. If you want to make a change to all environments, the process exists: you get it put into the spec. Since |
Today yes. In 2012... specs were stagnant and browsers just shipped shit and copied each other. My point above is that Iterators existed before ES6, even if not uniformly so (browsers did not used to be uniform) and their implementation is the one Immutable.js is designed to support. As opposed to Immutable.js desiring some non-standard Iterator implementation that had a non-material coincidentally similarity to these older environments. If it weren't for supporting those older environments then we'd probably remove it.
I'm not sure why this is our only path forward. It has significant downsides around type complexity and degraded error messages. It also doesn't solve the key problem that Perhaps another option to solve this could be done with two steps:
Especially after the first step, then an ES5-Firefoxish type def for Iterator becomes simply: lib.es5.iterator.d.tsinterface Iterator<T> {
next(): { done: boolean, value: T };
}
interface Iterable<T> {
['@@iterable'](): Iterator<T>;
}
interface IterableIterator<T> extends Iterator<T> {
['@@iterable'](): IterableIterator<T>;
} |
Alas, the runtime environment I'm in is server-side, not a browser and has no de-facto concept of In my scenario I have two runtimes to support - an ES5 compatible environment (Rhino) and an ES2019 environment (Graal). Also indirectly, ES6+ browsers). To support this with one build, I've been targeting ES5 which functions under both environments due to good backwards compatibility. I don't see a way to resolve a single global I'm inclined to perhaps just lock the current version of our library to Immutable < 4 and it would remain compatible in all runtimes. Then do a major version bump to target the newer runtime only and hence Immutable 4+. If my use case is really fringe I hate to waste your time. Admittedly, the majority of what we do now is in the newer runtime, but there's so much legacy code still running in that old runtime.... It's been nice over the years to be able to upgrade library and use it freely in either environment due to ES5 broad compatibility. |
@ShawnTalbert It sounds like perhaps you should just fork immutable 4 and publish |
Less costly than a fork would be just a fork of the type defs, since the runtime itself doesn't need to change. Considering that ES6+ Iterables depend on Symbol, and one of your constraints is that you don't want to introduce types that do not accurately reflect the environment you're operating in, then think it's going to be hard to describe one type for Options for you going forward:
|
To support pre-ES2015 environments where
Symbol.iterator
does not exist, recognizingthat the
Seq()
implementation does accept a 'false' Iterable in the form of an object that has aproperty named "@@iterator" which returns the Iterator.
Discussion on PR #1589