Complete Guide to Importing JavaScript Modules in TypeScript: From CommonJS to ES6 Modules

Nov 22, 2025 · Programming · 9 views · 7.8

Keywords: TypeScript | JavaScript Modules | CommonJS | Module Import | tsconfig.json | allowJs Configuration

Abstract: This article provides an in-depth exploration of complete solutions for importing JavaScript modules in TypeScript projects. Through analysis of the FriendCard.js module import issue in a Protractor project, it explains the working principles of TypeScript's module system, provides specific methods for importing CommonJS modules using import * as syntax, and introduces the crucial role of allowJs configuration in tsconfig.json. The article also discusses TypeScript's design philosophy as a JavaScript superset and best practices for mixing TypeScript and JavaScript in real-world projects.

Problem Background and Scenario Analysis

In modern front-end development, TypeScript, as a superset of JavaScript, provides powerful type systems and modular support. However, when projects need to integrate existing JavaScript codebases, developers often encounter compatibility issues with module imports. This article deeply analyzes how to correctly import CommonJS format JavaScript modules into TypeScript files, based on a specific Protractor testing project case.

In the original problem, the developer has a FriendCard.js file that uses traditional CommonJS module export syntax:

var FriendCard = function (card) {
    var webElement = card;
    var menuButton;
    var serialNumber;

    this.getAsWebElement = function () {
        return webElement;
    };

    this.clickMenuButton = function () {
        menuButton.click();
    };

    this.setSerialNumber = function (numberOfElements) {
        serialNumber = numberOfElements + 1;
        menuButton = element(by.xpath('.//*[@id='mCSB_2_container']/li[' + serialNumber + ']/ng-include/div/div[2]/i'));
    };

    this.deleteFriend = function () {
        element(by.css('[ng-click="deleteFriend(person);"]')).click();
        element(by.css('[ng-click="confirm()"]')).click();
    }
};
module.exports = FriendCard;

This module can be normally imported in pure JavaScript environments using require('./../pages/FriendCard'), but when using ES6 import syntax import {FriendCard} from './../pages/FriendCard' in TypeScript files, the TypeScript compiler reports error TS2305: has no exported member 'FriendCard'.

Deep Analysis of TypeScript Module System

TypeScript's module system is based on ES6 module specifications, but to be compatible with different module loaders, it provides flexible compilation options. When encountering CommonJS modules, TypeScript requires special handling to correctly recognize module exports.

CommonJS uses module.exports for module exports, which differs structurally from ES6's export syntax. TypeScript, by default, expects modules to use ES6 export syntax and therefore cannot directly recognize CommonJS export methods.

Referring to relevant discussions in the Microsoft TypeScript repository, developers frequently encounter issues with importing untyped JavaScript modules. As mentioned in the reference article, TypeScript, as a JavaScript superset, should theoretically be able to seamlessly integrate existing JavaScript code, but requires appropriate configuration in practice.

Solution: Complete Import Strategy

For the FriendCard module import issue, we provide two complementary solutions:

Solution 1: Using Namespace Import Syntax

The most direct solution is to use TypeScript's namespace import syntax:

import * as FriendCard from './../pages/FriendCard';

This syntax imports the entire module as a namespace object, allowing access to all exported members of the module. When using it, you need to access the exported constructor through FriendCard.default or by directly calling FriendCard:

const cardInstance = new FriendCard(someElement);
cardInstance.clickMenuButton();

Solution 2: Configuring TypeScript Compiler Options

To better support JavaScript module imports in projects, you need to enable the allowJs option in tsconfig.json:

{
  "compilerOptions": {
    "allowJs": true
  }
}

This configuration allows the TypeScript compiler to process JavaScript files, providing better support for projects mixing TypeScript and JavaScript. After enabling this option, TypeScript performs basic syntax checking on JavaScript files and provides limited type inference.

Deep Understanding of allowJs Configuration

The allowJs configuration option is an important feature provided by TypeScript that allows including JavaScript files in TypeScript projects. When this option is enabled:

This option is particularly important for projects gradually migrating to TypeScript. It allows teams to progressively convert JavaScript files to TypeScript without needing to rewrite all code at once.

Best Practices and Considerations

When adopting a mixed TypeScript and JavaScript development model in actual projects, it is recommended to follow these best practices:

  1. Gradual Migration: For large codebases, adopt a gradual migration strategy, progressively converting critical modules to TypeScript
  2. Type Declaration Files: Create type declaration files (.d.ts) for important JavaScript libraries to obtain complete type support
  3. Build Tool Configuration: Ensure build tools (such as Webpack, Rollup) are correctly configured to handle mixed TypeScript and JavaScript files
  4. Code Quality: Even when using allowJs, add JSDoc comments in JavaScript files to improve code maintainability

Conclusion

TypeScript, as a JavaScript superset, provides powerful tools to improve code quality and development experience. By correctly configuring tsconfig.json and using appropriate import syntax, developers can seamlessly integrate existing JavaScript codebases. The import * as syntax and allowJs configuration discussed in this article provide complete solutions for CommonJS module import issues, laying a solid foundation for teams' smooth transition from JavaScript to TypeScript.

As the TypeScript ecosystem continues to develop, there may be more tools and best practices in the future to simplify development of mixed-language projects. Currently, mastering these core concepts and technologies will help developers efficiently utilize TypeScript's powerful features in actual projects.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.