junichiro
junichiro

Reputation: 5492

Confused by the way TypeScript uses "require(...)"

I've tried reading several blog posts but TypeScript modules still have me totally confused. In particular, I have used 3 different modules (all installed via npm) and each seems to show totally different behaviour:

(1) I can import and use Angular 2 from npm like this in my .ts:

import {bootstrap, Component, Directive, CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/angular2';

Then in my html I have:

<script src="../node_modules/angular2/bundles/angular2.dev.js"></script>

This has the following results:

(2) The npm D3 module does not have a typescript definition, but I can download the one from DefinitelyTyped and then use it by putting:

/// <reference path="../../typings/tsd.d.ts" />

at the top of my .ts. and

<script src="../node_modules/d3/d3.js"></script>

in my html. It seems that being an old-style module it doesn't need an import statement, and as long as I leave it here the output JavaScript works fine. If I do try to use an import statement immediately after the reference line:

import * as d3 from 'd3';

then as with Angular2 it now adds:

var d3 = require('d3');

to the output JavaScript. However, unlike with the Angular case it doesn't realise it's already loaded the JavaScript via the script tag, and so the browser tries and fails to load a file simply called "d3" from the same directory as the html file, which fails.

(3) The npm Phaser module does include a .d.ts file, in a "typescript" subdirectory of the npm module. This is an old style module ("declare module Phaser"), so it seems I need not use "import.." syntax but instead just:

/// <reference path="../node_modules/phaser/typescript/phaser.d.ts"/>

at the top of my .ts file, as with the D3 example. The TypeScript compiler is happy, but unlike with the D3 example, under some circumstances (I haven't worked out quite what yet, doesn't seem to always happen) it outputs:

var phaser_1 = require('phaser');

in the JavaScript even when I haven't used an import statement. I'm not even using commonjs/requirejs in my phaser project, so "require" isn't even defined, causing failure.

And for completeness, unlike with either the Angular or D3 example, if I try putting an import statement after the reference line:

import * as Phaser from 'Phaser';

even the TypeScript compiler isn't happy. Perhaps in the D3 example the TypeScript compiler is treating the tsd.json or typings folder from DefinitelyTyped in special way, or maybe there is some other reason the import compiles for D3 but not for Phaser.

I have all sorts of questions:

1) What determines whether the TypeScript compiler includes a "require(...)" line in the output JavaScript?

2) Under what circumstances does the TypeScript compiler know where to find an external module in "npm_modules" when using "import", with or without needing a reference line at the top of the file?

3) Under what circumstances does the TypeScript compiler know where to find an ambient module in "typings" when using "import", with or without a "reference" line at the top of the file?

4) Under what circumstances does the TypeScript compiler know where to find an ambient module in "npm_modules" when using "import", with or without a "reference" line at the top of the file??

5) Maybe a commonjs/requirejs question rather than a typescript question, but if the TypeScript compiler does output a "require" line in the JavaScript, what do you do if the source of the JavaScript module is not set up with ES6 module exports?

Upvotes: 3

Views: 800

Answers (1)

basarat
basarat

Reputation: 276185

1 ) I can import and use Angular 2 from npm like this in my .ts:

This is because

  • angular2 ships with its .d.ts file

  • The browser doesn't attempt to read require because of magic in angular2.dev.js

The npm D3 module fails && the phaser module fails at runtime

They don't have the magic you get from angular2.dev.js. Use something like webpack or browserify to provide this magic.

Unlike with either the Angular or D3 example, if I try putting an import statement after the reference line: import * as Phaser from 'Phaser';

This is because of how Phaser definition is declared. Apprarently it is missing declare module "Phaser" which is what is provided with d3 see here and angular.

Upvotes: 3

Related Questions