Skip to content
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

Need to support declaration merging in external modules #2821

Closed
cnshenj opened this issue Apr 17, 2015 · 5 comments
Closed

Need to support declaration merging in external modules #2821

cnshenj opened this issue Apr 17, 2015 · 5 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@cnshenj
Copy link

cnshenj commented Apr 17, 2015

jQuery (jQuery UI) support method extensions. If we write my own jQuery UI widget, I can do this:
In myWidget.ts:

interface JQuery {
    myWidget(): JQuery
}

class myWidget {
    public foo() {
        // This is okay now, but will fail once we add some import statements to this file,
        // because TypeScript thinks this JQuery is not that JQuery
        var some: JQuery = $("#some-id").text();
    }
}

$.fn.extend({
    myWidget() {...}
});

Then in another file:

$(selector).myWidget(); // Create a new myWidget, this is okay because of myWidget() is declared in my version of JQuery interface
$(selector).attr("id", "my-id"); // This is okay because attr is declared in jquery.d.ts

However, this stops working when I add this line to myWidget.ts:

import helpers = require("helpers");

Now TypeScript thinks there 2 JQuery interfaces, instead of merging them into one. How do I tell TypeScript that I'm not creating a new interface for this module, but need to merge it with an existing interface?

@mhegazy
Copy link
Contributor

mhegazy commented Apr 17, 2015

by adding import or export to the top level scope in your file, you are truing this file into a module.

Modules, as per ES6 spec, have their own scope. so your interface JQuery is a local interface, and does not merge with the global JQuery. TypeScript does not provide a way to model modules affecting global state.

To do that, you have two options:

  1. Split your file into a .d.ts with the extension to JQuery, and your module would include that .d.ts using ///reference.
  2. do not use modules, i.e. no "imports" and it will be included globally as a script tag

Please note that ES6 modules have not supported this pattern, but rather a pattern of module composition, where you would import JQuery, add your extension, and export it again. users would only import your module instead of JQuery plus your module. e.g. export * from "JQuery".

@mhegazy mhegazy added the Question An issue which isn't directly actionable in code label Apr 17, 2015
@cnshenj
Copy link
Author

cnshenj commented Apr 20, 2015

I like the module composition solution. Is it supported by TypeScript yet?

@mhegazy
Copy link
Contributor

mhegazy commented Apr 20, 2015

@cnshenj ES6 module syntax is supported starting form TypeScript 1.5-alpha

@mhegazy mhegazy closed this as completed Jun 12, 2015
@masaeedu
Copy link
Contributor

@mhegazy

Please note that ES6 modules have not supported this pattern, but rather a pattern of module composition, where you would import JQuery, add your extension, and export it again.

Could you please illustrate this? How would this work when I have two different modules that add different things to JQuery?

@mhegazy
Copy link
Contributor

mhegazy commented Jan 14, 2016

See #6213 for the module augmentation support.

@microsoft microsoft locked and limited conversation to collaborators Jun 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

3 participants