If I use `module(“somelib”)` in typescript, it can

2019-05-05 19:34发布

问题:

I'm trying to use typescript with angularjs in the client-side.

I found if I use external modules, the generated js won't be run in browser.

controllers.ts

/// <reference path="./libs/underscore.d.ts"/>

import _ = module("underscore");

module test {
    export class Ctrl {

        constructor($scope:any) {
            $scope.name = "Freewind";
            _.each($scope.name, function(item) {});
        }
    }
}

The generated js will be:

var _ = require("underscore")
var test;
(function (test) {
    var Ctrl = (function () {
        function Ctrl($scope) {
            $scope.name = "Freewind";
            _.each($scope.name, function (item) {
            });
        }
        return Ctrl;
    })();
    test.Ctrl = Ctrl;    
})(test || (test = {}));

Which can't run correctly. But if I remove the module("underscore") part, it will be OK.

Since I have add underscore.js in the HTML, I think it should be something wrong with the require() method. How to fix it?

回答1:

There are two ways to load stuff in your HTML pages.

Bundling

The first one is to manually include all the script files in your page. You might run some kind of pre-release step to merge and minify your code - but you're taking responsibility for that instead of leaving it to the code to do. This is generally called bundling.

In the case on bundling, you only use references in your TypeScript code (not imports), like this:

/// <reference path="./libs/underscore.d.ts"/>

module test {
    export class Ctrl {

        constructor($scope:any) {
            $scope.name = "Freewind";
            _.each($scope.name, function(item) {});
        }
    }
}

Module loading

If you want to use a module loader, which for The Web is typically RequireJS, you can load External Modules using the import statement. Normally you wouldn't need the reference in this case...

import _ = module("./libs/underscore");

module test {
    export class Ctrl {

        constructor($scope:any) {
            $scope.name = "Freewind";
            _.each($scope.name, function(item) {});
        }
    }
}

RequireJS with non-modules

There is a third scenario, which is quite common. If you intend to import something that isn't an External Module (such as jQuery, but underscore may also fit this pattern), you are better off using a reference and a manual call to RequireJS.

RequireJS will load the dependency for you, so you would wrap your main program with it (which would probably be in a separate file such as app.ts.

///<reference path="./libs/require.d.ts" />
///<reference path="./libs/underscore.d.ts" />

module test {
    export class Ctrl {

        constructor($scope:any) {
            $scope.name = "Freewind";
            _.each($scope.name, function(item) {});
        }
    }
}

require(['underscore'], function (_) {
    var ctrl = new test.Crtl({});
});

You can also use require.config to specify the path to underscore in your application.

  require.config({
    paths: {
        "underscore": "libs/underscore"
    }
  });


回答2:

When you use require, you asserting that underscore is exported as a loadable module. This further assumes that you are using some sort of module loader system (TypeScript currently supports AMD and CommonJS modules). Since you aren't using a module system, and underscore is simply available in global scope, you can use a /// reference to tell TypeScript that Underscore is available in global scope. Put the following at the top of your file:

/// <reference path="./libs/underscore.d.ts">

And you should be good to go!