What is the importance of adding the ".js" extension when importing a custom module in Typescript?

This is a basic test involving async/await, where I have created a module with a simple class to handle delays

mymodule.ts:

export class foo {

    public async delay(t: number) {
                console.log("returning promise");
                return new Promise( resolve => setTimeout(resolve, t));
    };
};

This is the top-level TypeScript file used to call the function:

hello.ts:

import { foo } from './mymodule'

let f = new foo();

console.log("start");
await f.delay(4000);
console.log("done");

Although it builds without errors, when running the resulting hello.js with node (>node hello.js), an error is encountered:

Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'E:\tsdev\test\out\mymodule' imported from E:\tsdev\test\out\hello.js
Did you mean to import ../mymodule.js?
    at new NodeError (node:internal/errors:399:5)
    ...
    

If I modify the import statement to include ".js", like so

import { foo } from './mymodule.js'
, then everything works as expected.

E:\tsdev\test\out>node hello.js
start
returning promise
done

Trying different configurations in tsconfig and package files has not resolved this issue. Any help will be greatly appreciated.

Shawn

I've attempted various modifications to the tsconfig and package files.

Answer №1

If you're looking to utilize the official TypeScript compiler for generating JavaScript code, adding the appropriate extension is essential.

  1. Node.js doesn't support extensionless relative imports
  2. TypeScript doesn't automatically add import extensions during compilation

In cases where you wish to use extensionless imports in TypeScript, employing a bundler or alternative build tool capable of adding .js extensions becomes necessary. For instance, transcoding TypeScript to JavaScript via Babel and babel-plugin-add-import-extension can be a suitable option.

Nonetheless, relying on TypeScript (tsc) remains crucial for type checking and creating type declaration files, necessitating a tsconfig.json with compilerOptions.moduleResolution defined as "Bundler".

Below is an example configuration tailored for a library targeting Node.js 18.

.babelrc:

{
  "presets": [
    [
      "@babel/env",
      {
        "modules": false,
        "targets": {
          "node": "18"
        }
      }
    ],
    "@babel/typescript"
  ],
  "plugins": ["add-import-extension"]
}

tsconfig.json

{
  "extends": "@tsconfig/strictest/tsconfig.json",
  "compilerOptions": {
    "allowJs": false,
    "checkJs": false,
    "declaration": true,
    "declarationMap": true,
    "emitDeclarationOnly": true,
    "lib": ["ES2022"],
    "module": "ES2022",
    "moduleResolution": "Bundler",
    "sourceMap": true,
    "target": "ES2022"
  }
}

package.json scripts:

{
    "build": "run-p -s build:*",
    "build:main": "babel -x .ts -d dist src",
    "build:types": "tsc",
}

and some devDependencies:

{
    "@babel/cli": "^7.22.15",
    "@babel/preset-typescript": "^7.22.15",
    "babel-plugin-add-import-extension": "^1.6.0",
    "npm-run-all": "^4.1.5",
    "typescript": "^5.2.2"
}

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

The functionality of Angular 4's ngStyle sum operates as a string instead of a number

<div class="scroll-element-content" [ngStyle]="{'width.px': (this.width + this.trackWidth)}"> With this.width set to 400 and this.trackWidth set to 8: The combined width of .scroll-element-content will be 4008 (since the sum is treated as ...

Connecting the mat-progress bar to a specific project ID in a mat-table

In my Job Execution screen, there is a list of Jobs along with their status displayed. I am looking to implement an Indeterminate mat-progress bar that will be visible when a Job is executing, and it should disappear once the job status changes to stop or ...

In Javascript, check if an item exists by comparing it to null

I am working with a dropdown list that can be used for various types of data. Some of the data includes an isActive flag (a BOOLEAN) while others do not. When the flag is absent, I would like to display the dropdown item in black. However, if the flag exis ...

Unidentified file: Error reading property 'filename'

I have a function that retrieves the file name. The file name is displayed in an input field, but the background color of the input field is only visible when a file is selected and the file name is populated there. I would like the background color to b ...

Utilize an array as the response model in Amazon API Gateway using the AWS CDK

I am currently in the process of developing a TypeScript AWS CDK to set up an API Gateway along with its own Swagger documentation. One of the requirements is to create a simple endpoint that returns a list of "Supplier", but I am facing challenges in spec ...

Creating rectangular shapes on the canvas with the help of react hooks

I have a React+Typescript web application and I am currently working on implementing the functionality to draw rectangles on a canvas. My goal is to utilize React hooks instead of classes in order to achieve this. The desired outcome is to enable the user ...

Using Angular 2, you can pass an object as a parameter to a function

Is there a way to pass an object as a parameter in the DOM on this forum? Within my HTML code, I have the following: <div class="list-items"> <ul> <li *ngFor="let i of item"> <span (click)="onAdd({{newUser.us ...

Tips for resolving TypeScript object undefined error when utilizing object of model classes

I encountered an issue while working with an object of a class that retrieves data from an API. When trying to access this object in the HTML, I'm receiving error TS2532. Here is the relevant code snippet-- export interface TgtInfo{ Mont ...

Expanding the capability of a function by inheriting properties of either type any or unknown

Can you explain why the values of P1 and P2 are different in these type definitions? type P1 = (() => 22) extends {[k:string]:any} ? 1:2 //`P1 == 1` type P2 = (() => 22) extends {[k:string]:unknown} ? 1:2 //`P2 == 2` ...

Jest tests reveal potential errors indicating an object may be null

When running my Jest (typescript) test cases on mongoose Models, I encounter numerous errors such as: Error TS2531: Object is possibly 'null'. For example, consider the following code snippet where the error is reported on line 3: const user = ...

Maximizing the potential of mouse positioning in Angular

I am working with an Angular form that has a textarea <textarea class="form-control" id="message" formControlName="message" (fo ...

Creating a DynamoDB table and adding an item using CDK in Typescript

Can anyone guide me on how to add items to a Dynamodb Table using CDK and Typescript? I have figured out the partition/sort keys creation, but I am struggling to find a straightforward solution for adding items or attributes to those items. Additionally, ...

The exploration of child routes and modules

I'm currently working on a somewhat large project and I've decided to break it down into modules. However, I'm facing an issue with accessing the routes of admin.module.ts. In my app.module, I have imported the admin Module. imports: [ Br ...

The type 'Store<unknown, AnyAction>' is lacking the properties: dispatch, getState, subscribe, and replaceReducer

I have configured the redux store in a public library as follows: import { configureStore } from '@reduxjs/toolkit'; import rootReducer from '@/common/combineReducer'; import { createLogger } from 'redux-logger'; import thunk ...

Expanding a TypeScript interface across different modules

For my project, I am working with Highcharts typings and encountered a need to extend certain object/interfaces it defines by adding some custom properties. Here is an example: declare namespace Chart { interface ChartOptions extends Highcharts.ChartOpt ...

Drizzle ORM retrieve unique string that is not a database column

I'm working with a SQL query that looks like this: SELECT * FROM ( SELECT 'car' AS type, model FROM car UNION SELECT 'truck' AS type, model FROM trucks ) vehicles; In Drizzle, I'm trying to replicate the 'car ...

Error message: The property 'data' is not recognized within this context. Additionally, the property 'datatime' does not exist on the current type

I'm currently working on generating a graph using Firestore data and ng2charts. However, when I run my code, I encounter the following errors: Property 'data' does not exist on type 'unknown', causing an error in item.data Simila ...

Is there a way to omit type arguments in TypeScript when they are not needed?

Here is a function I am currently working with: function progress<T>(data: JsonApiQueryData<T>): number { const { links, meta } = data.getMeta(); if (!links.next) { return 1; } const url = new URL(links.next); return parseInt(url ...

Executing an HTTP POST request without properly encoding a specific parameter

I am attempting to communicate with an unauthorized third-party API using Node and the request module. Below is the code that generates the request: request.post( { url: url, headers: MY_HEADERS_HERE, followAllR ...

Exploring methods to broaden the functionality of components through inheritance

My goal is to develop extensions for existing Angular 2 components without having to completely rewrite them. I want any changes made to the base component to also automatically apply to its derived components. To illustrate my point, consider the followi ...