Is it possible to use ES6 import and require in Typescript 2?

In my Angular2 app, I have a class exported using ES6 modules:

//File = init.todos.ts

export class Init {
   load() {
      ...
    }
}

I am importing this class into another component like this:

//File = todo.service.ts

import { Init } from './init.todos'

Everything works as expected.

However, when I change the loading mechanism to commonjs:

//File = init.todos.ts
export class Init {
    load() {
       ...
    }
}
module.exports.Init = Init;

When trying to require it:

//File = todo.service.ts
var  Init = require("./init.todos");

I encounter these errors:

...myApp/src/app/todo.service.ts (4,13): Cannot find name 'require'.) ...myApp/src/app/todo.service.ts (12,14): Property 'load' does not exist on type 'TodoService'.)

https://i.sstatic.net/akUPR.png

Question:

How can I also load commonjs modules using require?

Tsconfig.json:

{
    "compileOnSave": false,
    "compilerOptions": {
        "outDir": "./dist/out-tsc",
        "baseUrl": "src",
        "module": "system",
        "sourceMap": true,
        "declaration": false,
        "moduleResolution": "node",
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "target": "es5",
        "typeRoots": [
            "node_modules/@types"
        ],
        "lib": [
            "es2016",
            "dom"
        ]
    }
}

Here are the config files :

tslint.json

tsconfig.json

package.json

angular-cli.json

webpack.config.js

Answer №1

Ever since version 1.5 was released, Typescript has embraced the ES6 style of imports.

Your code can remain untouched

//File = init.todos.ts

export class Init {
   load() {
      ...
    }
}

//File = todo.service.ts

import { Init } from './init.todos'

If you relocate the module property in your tsconfig.json to commonjs, the transpiler will produce commonjs compatible javascript allowing you to leverage and engage with the entire nodeJS ecosystem.

"compileOptions": {
    ...
    "module": "commonjs"
    ...
}

When wanting to import a preexisting NodeJS module into your typescript code, several scenarios may occur

  • the module includes incorporated Typescript Definition Files (with a "typings" entry in "package.json"). In this case, import the module using the ES6 syntax and you're all set (import * as blah from 'blah'). immutable.js serves as a great example

  • the module lacks Definition files but one is on hand at DefinitelyTyped, simply

    • execute npm install @types/blah to acquire the declarations for your project
    • and import the module as usual: import * as blah from 'blah'
  • the module doesn't have a definition file

    • you can create one, just add it to your project after naming it blah.d.ts. DefinitelyTyped offers a guide on this
    • opt to proceed without typings, simply utilize NodeJS require() const blah = require('blah'), and blah assumes type any (indicating that blah abstains from typing)

(in the interest of thoroughness, I could delve into the allowJS compiler option introduced since version 1.8, however, that deserves a discussion all its own)

Answer №2

TypeScript is fully compliant with ES6 standards. Utilize the ES6 module loading syntax within your TypeScript source code files:

import { SomeType } from './some.module';

When TypeScript transpiles to regular JavaScript, you have the flexibility to choose which module system to target:

"compileOptions": {
    "module": "commonjs" (or system, umd, amd)
}

Regardless of the module system you select, it's crucial to ensure that you include the necessary scripts and configuration to properly load the modules. For example, SystemJS, RequireJS, etc.

For practice, experiment with targeting different module loaders and examine the resulting .js file - the differences will be apparent.

Answer №3

Your question actually revolves around the issue not being with the require(...) method, but rather with referencing an error in Init. It seems like you are trying to lazy load modules using require. However, the problem lies in loading a class that contains an instance method load (which is not a class method - if you want it to be, you must declare it as static). Therefore, you need to create an instance before using it since require(...) returns any by default.

declare function require(id: string): any;

If you want TypeScript to infer the type correctly, you should declare the return type of require(). For example:

let foo: typeof Foo = require('foo')
. I noticed that the ts-jest test passes when module is anything except system, indicating that lazy loading is in play and the issue does not lie with the module itself. Here's a snippet of my test code:

Test

// To infer types for TypeScript
// This uses reference-elision optimization,
// so the module is loaded only when needed.
// Using InitClass as a type will be skipped.
import {Init as InitClass} from  "./init.todos";

test("TypeScript dynamic loading supports inferred types", () => {
    let Init: typeof InitClass = require("./init.todos").Init;

    let it = new Init();
    expect(it.load()).toEqual("bar");
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Checking nested arrays recursively in Typescript

I'm facing difficulty in traversing through a nested array which may contain arrays of itself, representing a dynamic menu structure. Below is how the objects are structured: This is the Interface IMenuNode: Interface IMenuNode: export interface IM ...

JS Equal Heights is a JavaScript plugin designed to ensure

Good evening, A while back, I implemented a JavaScript code snippet to create equal height columns on my website. The initial script looked like this: <script type="text/javascript"> var maxHeight = 0; $(".level").each(function(){ maxHe ...

Guidelines for verifying that a specified time falls within a designated range using Javascript

Need assistance with validating the start time and end time input values to ensure they fall within a specified range. Everything works fine when both times are on the same day, but encounters issues when the end date is different. I've searched throu ...

Using PHP, HTML, and JavaScript to generate a dropdown list from a database

I am looking to create a dynamic dropdown list populated from a database using JavaScript. My goal is to design a form where users can add multiple rows by clicking the "add more" button. The form will include both a text input field and a dropdown list. ...

Using React Higher Order Components with several different components

Is it possible to create a React HOC that can accept two components instead of just one wrapped component and toggle between them? For instance, in the code snippet below, rather than having <h3>component one</h3> and <h3>component two< ...

JavaScript: Manipulating Data with Dual Arrays of Objects

//Original Data export const data1 = [ { addKey: '11', address: '12', value: 0 }, { addKey: '11', address: '12', value: 0 }, { addKey: '12', address: '11', value: 0 }, { addKey: &a ...

Storing HTML values in a Meteor database is a common practice for web

Within my meteor project, I have a paragraph in HTML containing a JSON value as follows: {"Active Template Id":"6467","Shirt Brand":"levis","ProductId":"EB301","Brand":"on","Material":"cotton","Price":"1800","Combo Id":"S90"} I am looking to store this v ...

adhesive section on the left side with a defined lower boundary

I have a contact div that I made sticky using Bootstrap affix. <div id="contactForm" data-spy="affix" data-offset-top="400"> However, I am unsure of how to limit its bottom to the top of the next div. In other words, I want it to stay in place when ...

Validation of time picker consistently returns false

While using the daterangepicker library for my form validation with JavaScript, I encountered an issue with the time field. It returns false and displays an error message saying: "Please enter a valid time, between 00:00 and 23:59," preventing me from addi ...

Issue with binding click events on dynamically generated elements

After making an ajax call and successfully building button elements, I encountered an issue where I couldn't add a click event to the buttons. ... .done(function(data) { $('#data-message').empty(); $(&apo ...

Ways to stop Bootstrap 4 dropdown from appearing when clicking on an input field?

Here is a straightforward bootstrap dropdown menu example, but with a twist - the toggle element is a text input. Instead of showing the dropdown on click event, I want it to appear when the user inputs something so I can dynamically populate the menu base ...

Is it feasible to choose the component generated by this element?

My current dilemma involves a component that renders a form, however, it also has its own form "catcher". var FormUpload = React.createClass({ submit : function(){ var formdata =new FormData(); ...

The Raycast function seems to be failing to detect the GlTF file in Three.js

After creating a binary gltf file in Blender and animating it with Mixamo, I am encountering an issue where it is not being detected on raycast. Despite trying numerous tutorials and solutions, I have been unable to resolve the issue. const loader = new GL ...

Tips for concealing or revealing an existing element with *ngfor

I am currently facing an issue with hiding and showing an element in Angular 4. This is the HTML code I am working with: <div class='row'> <div class='col-md-4 imgTxt' *ngFor="let path of imagePaths" > <img [id] ...

Refreshing a paginated mat-table in Angular results in missing row data

My mat-table is designed to fetch data from firebase. AllMatchesComponent.html ... <mat-table #table [dataSource]="dataSource" class="mat-elevation-z8"> ... <ng-container matColumnDef="rank"> <mat-header-cell *matHeaderCellDe ...

I am looking to develop a customizable table where the user can input their desired information

Looking to create an HTML page featuring a 10x10 table with alternating red and green squares. After loading the page, a pop-up window will prompt the user to input a word, which will then appear only in the red squares of the table. While I've succes ...

The microservices system fails to initialize

I've recently delved into the world of microservices, but I've hit a roadblock in my application. app.listen(port) Despite adding .catch() I'm still unable to figure out what's going wrong. The function in question looks like this: nx ...

Tips for optimizing Angular source code to render HTML for better SEO performance

Our web platform utilizes Angular JS for the front-end and node js for the backend, creating dynamic pages. When inspecting the code by viewing the source, it appears like this: For our business to succeed, our website needs to be SEO-friendly in order to ...

Tree-view of Editable Boxes in Vue.js

I am working on a project and have created a fiddle for it: https://jsfiddle.net/pnqzspoe/12014/ My goal is to make some modifications to the code. I want each node to be displayed as a text area with the corresponding text inside. Additionally, I would ...

Identifying the element with the specified ID within the table's <th> tag in JavaScript

I want to create a table with the title: Summary Statement as of August 3, 2017 at 12:55 The date is functioning properly using JavaScript in other parts of the code, but not in this section. Is there a specific technique I should be aware of? The rest of ...