SystemJS and default import with export = proposal · Issue #5285 · microsoft/TypeScript (original) (raw)

I was recently running into some trouble with getting SystemJS to load jQuery using the ES6-style syntax.

import * as $ from 'jquery';

The above code worked fine with RequireJS and AMD format, and when using SystemJS as the loader when my code was emitted by TypeScript in AMD format.

However I noticed odd behavior when emitting this code using the system format and using SystemJS. I was getting all of the static functions of $, but $ itself was an inert object (not a function). So at runtime, $.isArray([]); would work, but $('#myDiv') would throw "$ is not a function".

Here's my original issue on the SystemJS repo: systemjs/systemjs#844

I kept digging around in the SystemJS documentation and eventually noticed that it referenced using a default ES6 import with jQuery:

Sure enough when I tried this, it worked, even though jQuery itself does not export a property default.

After more research, I found this on the SystemJS site:

https://github.com/systemjs/systemjs/blob/master/docs/module-formats.md#inter-format-dependencies

When loading CommonJS, AMD or Global modules from within ES6, the full module is available at the default export which can be loaded with the default import syntax.

So when using SystemJS, the "is a" is made available through a virtual default export.

However, this is a problem since there's not currently a way to model this in TypeScript without breaking existing code using import $ = require('jquery') syntax.

Current jQuery definition on Definitely Typed:

declare module "jquery" { export = $; }

Proposal

In light of the documented behavior of SystemJS, I'd like to propose a change to TypeScript to allow ES6-style default import syntax to work with an ambient external module declaration that uses export = syntax, as long as the module format is "system".

With this change, this code would compile cleanly if TypeScript is set to "system", but would still error using "amd", "commonjs" or "umd" with "Module 'my-module' has no default export":

my-module.d.ts

declare module "my-module" { var doStuff : () => void; export = doStuff; }

test.ts

import ds from "my-module"; ds();

Related:
#4337
#2719
CC: @vvakame @basarat @johnnyreilly @jbrantly @guybedford