简体   繁体   中英

How to configure TypeScript compilation for TS modules in an AngularJs application

I have discovered through the test described below that apparently, TypeScript 2.6.2 requires imported elements to be used in a new before the module is actually referenced in a require .

The following two blocks of code, taken from the official TypeScript documentation at the time of this writing, constitute the basis of the test I'm talking about.

ZipCodeValidator.ts:

export interface StringValidator {
    isAcceptable(s: string): boolean;
}

export const numberRegexp = /^[0-9]+$/;

class ZipCodeValidator implements StringValidator {
    isAcceptable(s: string) {
        return s.length === 5 && numberRegexp.test(s);
    }
}
export { ZipCodeValidator };
export { ZipCodeValidator as mainValidator };

SimpleModule.ts:

import { ZipCodeValidator } from "./ZipCodeValidator";

class Test {
    constructor(validator: ZipCodeValidator) {
        let myValidator = new ZipCodeValidator(); // <- NOTE THIS LINE.
        let x = 1;
    }
}

tsconfig.json:

{
    "compilerOptions": {
        "declaration": false,
        "emitDecoratorMetadata": false,
        "experimentalDecorators": false,
        "module": "CommonJS",
        "moduleResolution": "classic",
        "noFallthroughCasesInSwitch": false,
        "noImplicitAny": false,
        "noImplicitReturns": false,
        "outDir": "dist/scripts",
        "removeComments": false,
        "sourceMap": false,
        "strictNullChecks": false,
        "target": "es3"
    },
    "include": [
        "app/ts/**/*.ts"
    ],
    "compileOnSave": true,
    "buildOnSave": true
}

Transpiled ZipCodeValidator.js:

"use strict";
exports.__esModule = true;
exports.numberRegexp = /^[0-9]+$/;
var ZipCodeValidator = /** @class */ (function () {
    function ZipCodeValidator() {
    }
    ZipCodeValidator.prototype.isAcceptable = function (s) {
        return s.length === 5 && exports.numberRegexp.test(s);
    };
    return ZipCodeValidator;
}());
exports.ZipCodeValidator = ZipCodeValidator;
exports.mainValidator = ZipCodeValidator;

Transpiled SimpleModule.js (with the highlighted line left as is – One can see that there is a require call):

"use strict";
exports.__esModule = true;
var ZipCodeValidator_1 = require("./ZipCodeValidator");
var Test = /** @class */ (function () {
    function Test(validator) {
        var myValidator = new ZipCodeValidator_1.ZipCodeValidator();
        var x = 1;
    }
    return Test;
}());

Transpiled SimpleModule.js (with the highlighted line commented out – the require call has disappeared):

"use strict";
exports.__esModule = true;
var Test = /** @class */ (function () {
    function Test(validator) {
        //let myValidator = new ZipCodeValidator();
        var x = 1;
    }
    return Test;
}());

To me, this is problematic because I have converted an AngularJs application to TypeScript and I'm using modules instead of namespaces because I want to use Webpack for the build of reusable components each in its own module. I do not new things: AngularJs does that for me. And my intention with converting to modules written in TS was to end up with the benefit of fast startup time and dynamic module loading.

As a result, the transpiled JS code is devoid of require s even though exports are present in it. The bundle.js file built by Webpack is way too slim to actually contain everything that's needed.

Is there a way or setting to have the already present import {ServiceXYZ} from "./ServiceXYZ" TypeSscript instructions turned into the appropriate require calls?

The only way to make require to appear in generated code is through actually using some imported value at runtime, either by new or in some other way in the code.

TypeScript documentation says :

The compiler detects whether each module is used in the emitted JavaScript. If a module identifier is only ever used as part of a type annotations and never as an expression, then no require call is emitted for that module.

So, this is documented feature, and there are some people who are relying upon it , and I'm afraid there is no easy way around it.

This behaviour is specific to TypeScript imports . It removes potentially unused pieces of code and is welcome in most cases.

As long as ServiceXYZ remains unused,

import {ServiceXYZ} from "./ServiceXYZ" 

will be ignored. If module exports are potentially used, but it also provides side effects and should be imported any way, import should be duplicated:

import "./ServiceXYZ";
import {ServiceXYZ} from "./ServiceXYZ" 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM