Repository navigation
New APIs added to lib.d.ts may break client codes. Allow duplicated members in interfaces? Make lib.d.ts overridable? #3215
Description
Activity
Interfaces are open-ended... Once you strip out the collisions, you will only be left with the "extensions" to the interface you are making. For example, this is perfectly valid TypeScript:
interface Foo { bar: boolean; } interface Foo { qat: boolean; } var foo: Foo = { bar: false, qat: true };
Interfaces are open-ended -- I known.
The problem is: why should duplicated members in multiple parts of an interface be treated as error? I think duplications are perfectly legal if an interface is developed/maintained by multiple parties independently.Web APIs is a good example. Different browser vendors implement their own set of APIs. Largely the same, but have many small differences, e.g. vendor-prefixed APIs . Currently, TS's
lib.d.tsis based on IE's API, this is obviously limited. Ideally, every browser vendors should provide their own version oflib.d.ts, and developers can include some or all of them to achieve cross-platform-ness. An imaginary client code looks like:///<reference path='lib.ms.d.ts'/> ///<reference path='lib.webkit.d.ts'/> ///<reference path='lib.blink.d.ts'/> ///<reference path='lib.moz.d.ts'/> var requestFullscreen = document.requestFullscreen || document.mozRequestFullScreendocument || document.webkitRequestFullscreen || document.msRequestFullscreen; //...
But obviously this can't be done with current TS, because those
lib.nnn.d.tsfiles contain large amount of duplicated members of interfaces.- addedSuggestionAn idea for TypeScriptAn idea for TypeScriptIn DiscussionNot yet reached consensusNot yet reached consensus
on May 19, 2015 RyanCavanaugh commented
on May 19, 2015 MemberMore actionsThis is can be a giant pain. We should try to figure something out.
Make lib.d.ts overridable. When tsc find conflictions between lib.d.ts and client codes, it should pickup declarations in client codes.
FWIW this is allowed when compiling with
--nolibflag.Feel like recommending that
lib.d.tsbe removed from core and spinned into an external project maintained by MS + community.FWIW this is allowed when compiling with --nolib flag.
No, I just want to override the conflicting pieces, not
lib.d.tsentirely. Maintaining a wholelib.d.tsmyself is not practical (and there arelib.d.tsused by IDEs).Feel like recommending that lib.d.ts be removed from core and spinned into an external project maintained by MS + community.
Good idea. However it is still nice to allow duplication/overriding of declarations, because there is still no guarantee that individual parties that maintaining those declarations keep in sync with each other.
Another use case for this: if a project wants to target both ES5 and ES6, they have to include polyfill declarations for ES5 emit (eg.
Promise) but change the build to remove these for ES6 emit. It would be easier if bothes6-promise.d.tsandlib.es6.d.tscould be present to the compiler, so long as they don't conflict.There should be no harm in multiple declarations of the same interface as long as there are no conflicts.
Another option would be conditional compile, something along these lines:
#ifdef Promise
...
#elseif
...
#endif
This needs to be resolved soon, it is getting really painful to target both es-5 and es-6This needs to be resolved soon, it is getting really painful to target both es-5 and es-6
What is wrong with just including lib.es6.d.ts in your project? the library is a super set of ES5 one, and if your project targets both, and you have the correct pollyfils, then you should be safe.
I have two different node packages defining Iterable and IEnumerable interfaces. Including lib.es6.d.ts would not solve that problem because it also defines Iterable.
How about these who will add *.d.ts of my package? I can not require them do add lib.es6.d.ts as well.
What is wrong with ignoring duplicates?This issue also affects DefinitelyTyped potentially. Currently there are definations for webrtc, web speech, web midi, and firefox/chrome specific apis, etc, which will confilict with future TS releases. It is even harder for web developers to resolve such conflicts. One can't simply drop DefinitelyTyped because
lib.d.tsdoesn't contains all vendor prefixed APIs.I think ideally switching ES5/ES6 targets should not involve changing
lib.d.ts, and "compatibility note" suggested in #3250 is a better alternative. There are some ES7 APIs to be added to TS soon, do we want yet anotherlib.es7.d.ts?- removedIn DiscussionNot yet reached consensusNot yet reached consensus
on Aug 3, 2015 RyanCavanaugh commented
on Aug 3, 2015 MemberMore actionsWrite up proposal for decoupled libraries
30 remaining items
- added@typesRelates to working with .d.ts files (declaration/definition files) from DefinitelyTypedRelates to working with .d.ts files (declaration/definition files) from DefinitelyTyped
on Feb 22, 2016 I have another use case:
There is a third party library that has started creating their own type definitions - unfortunately many of the interface members are just stubbed with type any, which is nearly useless.
Even with the proposal here, I cannot override the provided type definition with the type I know to be correct. The type definition itself can be updated, but in the next version you'll have to start over.
- addedCommittedThe team has roadmapped this issueThe team has roadmapped this issueand removedIn DiscussionNot yet reached consensusNot yet reached consensus
on Apr 11, 2016 RyanCavanaugh commented
on Apr 11, 2016 MemberMore actionsReference Type directives are designed to solve exactly this problem by providing a canonical lookup location for things which mess with the global scope.
Combined with the library decoupling work, I think we're addressing all the scenarios here as best as is feasible. There will need to be some level of restructuring of code that found itself in this state, but fundamentally it is solving the problem where two people both want to declare something in the global scope.
Reacted by Ryan SmithRyan Cavanaugh (@RyanCavanaugh) Do you mean Library include directives? It is a very useful feature, but I'm not sure how "duplicated identifer" is resolved. Is it still an error to declare an identical member in a global interface in client code?
It is a very useful feature, but I'm not sure how "duplicated identifer" is resolved
It doesn't. But it allows library declaration authors to not pollute the global namespace. Thus decreases the likelihood of global namespace collision 🌹
RyanCavanaugh commented
on Apr 12, 2016 MemberMore actionsIt solves it because the offending declaration files can be rewritten to be included via library directives, which will only happen once
I want to use some DOM4 APIs and installed dom4 typings (
typings install -A dom4). What will happen when some DOM4 APIs are added tolib.d.tsin future? E.g.interface ParentNode { children: HTMLCollection; }
I also note that duplicate method in interface is not an error, but duplicate property is.
E.g.interface Element { innerHTML: string; // error: duplicate identifer getAttribute(name?: string): string; // OK getAttribute: (name?: string) => string; // error: duplicate identifer }
This is a strange divergence to me.
Reacted by Piotr Mionskowskifacing same issue in beta17
- addedFixedA PR has been merged for this issueA PR has been merged for this issue
on Jun 20, 2016 This is really annoying when trying to compile to es6 - and I am not talking about Angular ,it is valid for any TS project (in my case electron application).
If any of your dependencies has types/es6-promise as dependency you get the duplicated Promise error mentioned above.
Now your options are (as far as I can see):
- delete es6-promise package on pre-build step (ghhhh)
- define some crazy interfaces and use them instead Promise (2x ghhh)
- switch to es5 :(
Kiril Popov (@kirilpopov) the other option is to manually
excludewhatever the type file that is providing the typing in thetsconfig.json.- locked and limited conversation to collaborators
on Jun 19, 2018
I noticed that recently a lot of new APIs are added to
lib.d.ts. Of cause this is a good thing, however my code breaks badly because of such update.Previously I had added a lot of declarations in my code for HTML5 APIs that were missing in
lib.d.ts. Now some of them are added tolib.d.ts, and I get quite a few "duplicated identifier" errors. For example, I had added this piece to play with fullscreen:Now
fullscreenEnabledandwebkitFullscreenEnabledare available inlib.d.ts, and my code breaks, and I have to remove them. However, you are still missingmozFullScreenEnabledright? -- well, waiting for the next break.Web platforms are constantly evolving, it is not practical to expect
lib.d.tsalways up to date, so developers just have to write such compensating declarations from time to time. Can TS avoid such breaks? I have a few ideas:lib.d.tsoverridable. When tsc find conflictions betweenlib.d.tsand client codes, it should pickup declarations in client codes. This is because declarationslib.d.tsmay contain bugs, developers should be allowed to workaround them. E.g.MutationObserver's constructor was missing a parameter for a long time. Again, optional warnings are welcomed.What do you think?