Incorrectly importing unused exports

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
Generated main.js contains code for SomeClass and OtherClass

generated main.js

(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["main"],{

/***/ "./src/OtherClass.ts":
/*!***************************!*\
  !*** ./src/OtherClass.ts ***!
  \***************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
class OtherClass {
    constructor() {
        console.log('OtherClass');
    }
}
exports.OtherClass = OtherClass;


/***/ }),

/***/ "./src/SomeClass.ts":
/*!**************************!*\
  !*** ./src/SomeClass.ts ***!
  \**************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const OtherClass_1 = __webpack_require__(/*! ./OtherClass */ "./src/OtherClass.ts");
var MyEnum;
(function (MyEnum) {
    MyEnum["on"] = "on";
    MyEnum["off"] = "off";
})(MyEnum = exports.MyEnum || (exports.MyEnum = {}));
class SomeClass {
    constructor() {
        const o = new OtherClass_1.OtherClass();
        console.log('SomeClass', o);
    }
}
exports.SomeClass = SomeClass;


/***/ }),

/***/ "./src/entry.ts":
/*!**********************!*\
  !*** ./src/entry.ts ***!
  \**********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const SomeClass_1 = __webpack_require__(/*! ./SomeClass */ "./src/SomeClass.ts");
console.log(SomeClass_1.MyEnum);


/***/ })

},[["./src/entry.ts","webpack-runtime"]]]);

If the current behavior is a bug, please provide the steps to reproduce.
Basic setup
npm i webpack webpack-cli ts-loader typescript

files
webpack.config.js

const path = require('path');

module.exports = {
    entry: {
        main: './src/entry.ts'
    },
    mode: 'development',
    devtool: 'none',
    resolve: {
        extensions: ['.ts', '.tsx', '.js'],
    },
    optimization: {
        runtimeChunk: {
            name: 'webpack-runtime'
        }
    },
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                loader: 'ts-loader'
            }
        ]
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js',
    }
};

tsconfig.json

{
    "compilerOptions": {
        "module": "commonjs",
        "moduleResolution": "node",
        "pretty": true,
        "lib": ["dom", "es6"],
        "target": "es6"
    },
    "exclude": [
        "node_modules"
    ],
    "include": [
        "src/**/*.ts"
    ]
}

src/entry.ts

import {MyEnum} from './SomeClass'
console.log(MyEnum);

src/SomeClass.ts

import {OtherClass} from './OtherClass';

export enum MyEnum {
    on = 'on',
    off = 'off'
}

export class SomeClass {
    constructor() {
        const o = new OtherClass();
        console.log('SomeClass', o);
    }
}

src/OtherClass.ts

export class OtherClass {
    constructor() {
        console.log('OtherClass');
    }
}

Run
npx webpack

What is the expected behavior?
Generated main.js should not have any references to SomeClass, OtherClass as it only imported the enum.

Please mention other relevant information such as the browser version, Node.js version, webpack version, and Operating System.

node v9.2.0

package.json

 "ts-loader": "^4.0.1",
  "typescript": "^2.7.2",
  "webpack": "^4.1.1",
  "webpack-cli": "^2.0.12"

Additional Notes
It is worth noting the following setup does work correctly as SomeClass is never accessed it is only used for type definitions.

Change entry.ts to the following

import {SomeClass} from './SomeClass'

const a:SomeClass = null;
console.log(a);

Results in
generated main.js

(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["main"],{

/***/ "./src/entry.ts":
/*!**********************!*\
  !*** ./src/entry.ts ***!
  \**********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const a = null;
console.log(a);


/***/ })

},[["./src/entry.ts","webpack-runtime"]]]);

Workarounds

Use const enums as they are removed upon compilation

import {OtherClass} from './OtherClass';

export const enum MyEnum {
    on = 'on',
    off = 'off'
}

export class SomeClass {
    constructor() {
        const o = new OtherClass();
        console.log('SomeClass', o);
    }
}

or

Move interface and enum declarations into another file and import them into both entry.ts and SomeClass.ts

Author: Fantashit

1 thought on “Incorrectly importing unused exports

  1. Your tsconfig.json is incorrectly set up. It’s compiling the module to commonjs, instead of leaving es2015 or esnext modules.

Comments are closed.