-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
es5.d.ts lib does not match the ECMAScript 5.1 Spec #16132
Comments
I think the empty interfaces or the inclusion of Promise in lib.dom.d.ts are good, but they do not remove your problem with incorrect suggested type, right? Because by default DOM types are included and then you will still get Promise type by default. |
This issue is not at all concerned with the default and explicitly states as much:
The DOM is included by default, yes, as it is extremely common to write frontend (browser) code. However, it is possible to customize the environment such that DOM APIs are removed (e.g. The basic issue is that when I specify "ECMAScript 5" as my environment, I do not expect to see As for the default, one might argue based on the current ES6 API coverage in browsers that it should be updated to point to ECMAScript 6. But that is a different issue. |
It seems there are no defined semantics associated with use of the --lib switch/config entry, so exactly what --lib es5 should do or include seems arguable. I can't be alone in knowing of and depending on some of the definitions that this issue proposes should be removed, and such dependencies expand every day (see for example comment on this PR). Making a breaking change that would impact others to match some inferred definition of --lib es5 semantics seems unwise.
I think this over-interprets the comment made in #1995, which says "you can" rather than "you should". That comment seems to have been meant as a helpful how-to workaround, not a definition of philosophy of the library files. |
Do you really think so? You don't think that someone explicitly saying "I want only es5 types" is expecting to see Decorators (a feature which is still in proposal mode)? As a TypeScript user unfamiliar with the internals, would I not be surprised to see Promises and Typed Arrays show up when I attempt to limit the environment to ECMAScript 5.1 built-ins?
You most assuredly aren't! And I address the "expanding every day" issue in the initial post. If you look at the timeline of those features, you'll see that the es5 library "evolved" out of a core.d.ts file. The comment you linked to doesn't show "Decorators entering the es5 lib", it simply refers to the Decorator type definitions in ES5 after that switch. You can see where those definitions initially came in here, back when the es5 library was known as "core". It should be noted that this all happened before or as TypeScript gained the ability to specify specific libraries for the environment to include by default. The thing is that the ES5 library was never fully cleaned up - it was too difficult at the time to properly pull things apart such that ES5 could be, well, spec-compliant. But things have improved dramatically since then.
What are you implying by stating "inferred definition of --lib es5"? Almost every single other library you can specify attempts to match the spec it refers to. The es5 lib is a special case due to it's evolution. This Issue simply calls this out as being odd and something that should be fixed. The es5 standard (ECMAScript 5.1) is well-defined. I would highly suggest taking a look at the discussion #16077 (and especially the comments starting here. The TL;DR of the discussions there is that work has been done to create an es3 library and the initial approach was to simply move some types (e.g. Typed Arrays) out of es5 into es3. The current working approach is to break out the specific features called out at the top of this issue into their own libraries. With this approach, the default setup would be protected, the language type libraries would actually match the specs, and certain features could be added as needed. Users who currently rely on all features included in
The portion of the quote that you're referring to was included for context. The portion that does speak towards "philosophy of the library files" is the portion that I emphasized in bold. To reiterate, that is specifically:
What, then, are Decorators doing in ES5? They haven't even made it out of Draft stage and aren't supported in any current engines (beyond TypeScript itself). |
@ericdrobinson, Who says that Of course it The statement that "lib file reflects the baseline of engines supporting the target of the compilation" isn't really applicable to the decorator support types anyway, decorators don't need JavaScript engine support. They are handled by TypeScript, and thus decorators can be made to work on es5 engines, if the developer chooses to use them (which is controlled by a separate switch.) I'm painfully aware that decorators haven't stabilized yet, but that's an entirely separate discussion. |
@BurtHarris Wait, wait, wait, wait, wait. You're talking about code generation here, yes? That implies you don't mean to talk about the
Basically, Note further that Apologies if you were already aware of this. I just want to make sure we're on the same page. Your example above talks about expectations of an actual "target running engine". Substituting other
To be clear, the breaking change you're concerned about here is that once you upgrade to a newer version of TypeScript you'd have to add an extra option or two to the The issue is that having those types show up in auto-correct/IntelliSense can be confusing for people who specifically say "I want ES5-features only, thank you very much." And for less-obvious features, seeing such types may send people on a bit of a wild goose-chase to figure out if there's an option there they can use. Such [repeated] experiences prompted the creation of this very issue.
Right. This is where you would specify It should be noted that it appears as though @rbuckton's current proposal would potentially take "several releases" to fully realize... If your fear is related to a deprecation period, this may actually already be under consideration... |
No @ericdrobinson, I'm not talking about code generation. I'm talking about the ambient definitions assumed present by TypeScript without explicit
Here we go again, you writing quoted phrases, and I'm asking where you are quoting from. It looks to me like is that you are taking the definitions you have inferred and treating them as if they are somehow documented intent of the language designers. Now you are citing a PR comment by @rbuckton containing the word "perhaps" as a his current proposal. I think that stretches credibility, especially after he's explicitly told you "You either misread or misquoted me" in that same PR. Please think carefully about the lengths you seem to be going to in order to justify your point of view... you might start by assuming people mean what they say. The documented meaning of
Yes, that's mostly correct. That is a breaking change. Imposing your interpretations of intent could cause other innocent component to fail. But you are incorrect about it only applying if I've specified a If you really want purity of the ambient namespace, perhaps you should be using the |
I suggest this issue should be closed as by-design. |
@BurtHarris I think the TS team agrees that we should bring non-ES5 types out. #16077 (comment) #16077 (comment) |
Understood. I was clarifying because the statement you used in your example specifically mentioned the engine the code would run in. This was confusing in the moment. I was just trying to make sure we were on the same page. Glad it's cleared up!
I am aware of that but perhaps wasn't being as explicit as I should have been. In the discussion on #16077, special care was given to ensure that lib.d.ts (at least) would not be affected by the migration of non-es5 types into their own libraries. I would assume that such a change would also adjust the default libraries injected "when This still leaves the changes necessary for people simply specifying
Hmm... The quotes in the blocks of text that you cite are paraphrases/interpretations - they are not specific quotes. Most of the time I use Markdown Quote formatting when I'm specifically referencing someone or a specific page. The exception to this is the handful of times that I use them to link to a sentence fragment in a previous comment. In the first block you cite, for example, the quotes are reinterpretations of the [honestly rather thin and unclear] descriptions from the Compiler Options definitions that I directly quoted immediately prior.
I'm not really sure how best to respond to this. I'm not trying to suggest that the status was 'official proposal', only that 'one option has been proposed.' It's simply the latest idea on how it might be effected - one proposal as to how it might be implemented. Also, if you follow the discussion, the "perhaps" that I quote wherein an option is presented actually follows the "You either misread or misquoted me" quote that you cite. I responded directly to that statement in a follow-up comment to which he then responded in-kind with "I think I see what you are getting at. Perhaps the best breakdown would be..." In short, there was a bit of mutual-misunderstanding. Once that was cleared up, however, the most recent option/proposal (to which I linked) was put forth. It fell out of the constructive discussion.
Great! That is valuable feedback! Perhaps a suggestion that would work around all of this would be to add another option to the
Well, but specifying |
You can accomplish that using |
This is correct. The DOM doesn't follow the same versioning scheme as ECMAScript, so we're effectively trying to map an N-dimensional versioning space into a single dimension, which is definitely lossy. My main concern here is that this is a cure that is potentially much worse than the disease. We still don't actually bring in the values of the 'future' runtimes into scope, so you can't really write expression code that tries to access a non-existent value. And arguably it's not actually incorrect to use e.g. an ES6 type in an ES5 codebase -- if you write This gets really confusing if you consider libraries that work perfectly in ES3/ES5 environments, but still understand ES6 constructs if given them. If a library knows how to call |
Sure. But maintaining that across multiple projects is a headache and would imply extraneous upkeep costs as enhancements/fixes/changes continue in the root es5 default lib. Further, it leaves the issues raised in the last section of the initial post unaddressed. |
@ericdrobinson see the docs on |
@RyanCavanaugh Wouldn't this case be addressed by @rbuckton's suggestion here? In that world the ES3 user wouldn't include " |
@BurtHarris Right. Unfortunately that doesn't help address the issues I referenced here (upkeep/maintenance as well as leaving the initial concerns outlined in the Issue unaddressed)... |
Eric, I assert it helps, without doing the job for you. It shows the language designers already have an approach that allows default libraries to be replaced without requiring changes to the core default libraries. If you want to get more specific about headaches you might have with that approach, that topic belongs in a separate issue. Everyone admits that es5.d.ts is effectively a kludge, but it's now a feature of TypeScript. The existing design serves a useful purpose, however it wasn't designed to do what you think it should do, and that's what I mean when I say this should be closed as by-design. I know, from over 17 years as a dev at Microsoft, that by-design isn't a very satisfying outcome for an issue, but it really is what applies here. I'm retired now, and was never on the TypeScript team, but I've got investments in other projects to think about, and from my point-of-view this is a safer way to approach evolution of TypeScript than "pure" es5 arguments. |
There is provably correct and practical. JavaScript and related browser technologies have almost never been provably correct, and therefore we have to continue to approach them in a practical manner, including TypeScript's approach to typing them. Just from a language standard iOS 9 still did not properly implement ES5 let alone all the other technologies that are from that era. |
Understood. That doesn't change the facts about this issue. This is a workaround for a kludge and some potential options for fixing the kludge have been presented. I think the issue has already been productive.
The same exact thing could have been said about the original
It isn't just about ES5, but ES3 and what will happen as new features are proposed and added. Decorators are one good example - why are those types somehow blessed into what is effectively a renamed core? Why not other proposals? [Yes, I get that they're a[n experimental] feature of TypeScript. They could be in a separate library that's auto-added when specifying the If this gets changed as "by design", it won't change the fact that the status quo is confusing and very undocumented. From the original issue description:
Even a handful of comments in the libraries explaining, for example, 'This is a kludge. They're included for [reasons]' would be preferable to what exists right now. |
And TypeScript used to put everything (or near enough) into a single
This is true. But it doesn't mean that there isn't value in having spec-compliant libraries. If you really wanted to handle that problem, you'd build the system such to support "versioned JavaScript engine profiles." These would be built using a tool like Modernizr that users could run if an official version didn't exist in some centralized repository. As such you could have libraries like safari.ios.9.0.1.d.ts and chrome.46.0.2490.d.ts. In such a world you could specify a set of such libraries to define your target supported feature set (the system would rely upon the intersection of features across all listed libraries). Then you would know exactly what types you could use and what would need to be polyfilled/transpiled. But this is besides the point and is, I believe, why TypeScript still defaults to outputting ES3. |
After four years of watching this, I think the concerns here are entirely based on technical purity, but the downside problems created by messing with this are very much manifest. The ES3/5 distinction is unfortunate, but ES3 runtimes are dinosaurs at this point, rendering the problem largely moot. No action planned here. |
I'm not sure that's fair. With that argument, you could basically just go back to sticking everything in a "core ES lib" and tell everyone "You should know what your engine supports." No one here was arguing to separate ES3 from ES5 simply because "it would bring harmony to the ES universe" 😉
While those four years may have been improved for some by having ES3-specific type declarations, I have to agree that, at this point, the dinosaurs that I, at least, am concerned about are almost gone (or other solutions have worked themselves out).
Good call. 🍻 |
Types in es5.d.ts Should Match the ECMAScript 5.1 Standard
As a TypeScript user, I expect that an environment configured with
"lib": ["es5"]
should only resolve types specified in the ECMAScript 5.1 Language Specifications. Any further type declarations necessary should be optionally imported or specified by the TypeScript user. Indeed, this appears to be the suggested usage, as pointed out by @mhegazy in #1995 (emphasis mine):However, including only the "es5" lib will also bring in the following non-ES5 types (and their support types):
PromiseLike
- This was pulled into core.d.ts from es6.d.ts on 2015/05/05.ArrayBuffer
andTypedArray
s - This was merged into core.d.ts from es6.d.ts and extension.d.ts on 2015/08/15.Promise<T>
- This was pulled into es5.d.ts from es2015.promise.d.ts on 2016/02/13.Including these types breaks expectations in properly initialized environments and has the potential to lead to confusion, if not bugs.
Why Are These Types In es5.d.ts to Begin With?
In short: to support the DOM API declarations.
From what I've been able to glean from the history, the fact that the above type declarations exist in es5.d.ts is effectively a kludge to more simply support the constantly-evolving DOM API libraries. From the comments on #14053 (which brought
Promise<T>
into es5.d.ts):Indeed, supporting DOM APIs appears to explain much of the reason for including the previously listed types in es5.d.ts. Again, in #16077 we have the following comment:
[It should be noted that in the above case, the discussion revolves around whether or not to move the types further back in time (to ES3).]
Moving "Support" Types Out of es5.d.ts
So the types are defined in the ES libs to support the DOM APIs (which suffer from granularity issues). Here are some options for how they might be removed from the es5.d.ts file:
1. Create a Middleman Library
It appears that ES5 is used as the default ECMAScript library for TypeScript - at some point es5.d.ts was even called core.d.ts. But a core.d.ts could still exist: it could import es5.d.ts and then some extra "support" types (e.g. those outlined above). That file could then be specified in the lib.d.ts library source map (as well as others).
2. Specify Necessary Features Directly in the Library Source Map
Specific features that DOM APIs require might be included from their respective "future" libraries. An example for promises might look like:
provided
Promise
type interfaces were moved back into es2015.promise.d.ts (unless I'm missing something important).3. Declare Necessary Interfaces Inline
Declare required, but possibly new/future types as empty interfaces inline in the libraries that require it. In at least one Node Type Declaration library I've encountered, they did just this:
What's more, this even seems to be a suggested approach (emphasis mine):
Wrap-up: Being Explicit About Type Definition
Instituting a change like this would not only clean up the ECMAScript type declaration file(s), it would explicitly document why those types were included with certain libraries. Presently, a user trying to figure out why
UInt8Array
is a suggested type when they've only imported type declarations for ECMAScript 5 ("lib": ["es5"]
) will find that it's confusingly included in the es5.d.ts file, sans any documentation for its mysterious inclusion.Further, it would decouple DOM support from ECMAScript support, enabling users to more explicitly configure their environments without surprising side-effects.
The text was updated successfully, but these errors were encountered: