Reputation: 4474
I am using Visual Studio to create a ASP.NET Core 2.2 web app using TypeScript, and I have included the two.js
library along with the two.d.js
(TypeScript declaration file) from the npm package I've found online.
The problem is that I don't understand how to get modules working (perhaps it's not related to two.js
but using plain JavaScript with modules in general).
two.js
file uses JSDoc, but doesn't have any exports as far as I can see.
So my project has these files (two.d.js, two.js and site.ts):
+ js
- two.d.js
- two.js
- site.ts
- something.ts
And site.js
file is importing two.js
and something.ts
at the beginning:
// this uses the 'two.d.js' file and I get intellisense
import { Two } from "./two";
// this is some .ts file
import { Something } from "./something";
// create the Two.js instance
let placeholder = document.getElementById('placeholder');
// this line is what I want to get running
let twojs = new Two({ width: 1900, height: 885 }).appendTo(placeholder);
However, when site.ts
gets compiled, any modules option I try fail in the browser:
"None" (i.e. no module system): Fails with exports
is not defined in the first line of the compiled site.js
file:
Object.defineProperty(exports, "__esModule", { value: true });
ES2015 native module system: Fails with "404 not found" for ./something
and ./two
.
TypeScript compiler doesn't append the .js
extension to the native browser import
statement, so these files cannot be loaded. However if I add the extension in TypeScript then I get a compile error.
AMD/RequireJS: I get the "Two
is not a constructor" exception.
Code gets compiled to this and I can see all .js
files loaded correctly, however I guess the problem is that two.js
doesn't export anything natively:
define(["require", "exports", "./something", "./two"], function (require, exports, something, two_1) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
let placeholder = document.getElementById('placeholder');
// Two is not a constructor
let twojs = new two_1.Two({ width: 1900, height: 885 }).appendTo(placeholder);
});
Ideally, I would like to have a single bundled .js file per each page to reduce module loader server roundtrips, but I am open to other options.
Upvotes: 4
Views: 1203
Reputation: 19947
The two.js
is not exporting anything, it's exposing Two
as a global variable, thus the two.d.ts
is bluntly WRONG at type-annotating the module (in fact two.js
doesn't qualify as a "module"). You need to correct it first.
You need to replace all top-level export
keyword with declare
keyword in two.d.ts
. That'll tell TS two.js
is NOT a module and instead it exposes some global variables.
site.ts
can now directly refer to Two
the global variable, no more import
needed. As a good practice, it's advised to place a triple slash directive at the top of this file to show the dependency relationship. This will also put the content of two.js
before site.js
when bundled (see next step).
/// <reference path="./two.js" />
let twojs = new Two({ width: 1900, height: 885 }).appendTo(placeholder);
tsc
in command line, it will compile and bundle all your .js
and .ts
file into one single file. You might need to config "include" (or "files") field to cover all related resource, (e.g. two.js, two.d.ts) according to your project's file structure. Docs{
"include": [...],
"compilerOptions": {
"module": "amd",
"outFile": "bundle.js",
"allowJs": true // to include `two.js` into the bundle
}
}
<script data-main="scripts/bundle" src="scripts/require.js"></script>
Upvotes: 2