Run TypeScript with module import and definition using ts-node

I am attempting to initialize a database using TypeScript.

Here is my TypeScript code:

import { User, UserRole } from '../entity/User';
import crypto from 'crypto';
import {dbManager, pwhash } from '..';

async function inituser() 
{
    const user = new User();
    user.email = '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="fe8d969b9099d0928bbe938fd09b9a8bd09f8b">[email protected]</a>';
    user.own_organization = []
    user.salt = crypto.randomBytes(16).toString('hex');
    user.password = pwhash("password", user.salt);
    user.role = UserRole.admin;
    await dbManager.save(user);
    const duser = await dbManager.findOne(User);
    return duser;
}
const duser = inituser();

console.log("Loaded users: ", duser);

When I try to run the script using ts-node like:

npx ts-node db/initializers/inituser.ts

An error occurs:

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:1167:16)
    at Module._compile (internal/modules/cjs/loader.js:1215:27)
    at Module.m._compile (/usr/lib/node_modules/ts-node/src/index.ts:858:23)
    ...

To resolve this error, I added "type": "module" in the package.json file.

{
  "name": "typescript-test",
  "version": "1.0.0",
  "type": "module",
...
}

This change was made to address the warning message regarding loading an ES module.

(node:3854) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)

Answer №1

An issue arises with the Error message stating,

Warning: To load an ES module, set "type": "module" in the package.json or
, which has been linked to a Bug in ts-node: https://github.com/TypeStrong/ts-node/issues/935

This Bug has since been marked as closed, but there is still an ongoing discussion on how to resolve it: https://github.com/TypeStrong/ts-node/issues/1007

Despite claims, I find that specifying

"type": "module"
in package.json is unnecessary.

My tsconfig.json file utilizes

"module": "commonjs"
rather than
"module": "es6",
.

Until the resolution of ts-node issue #1007, this remains a noted technical debt.

Answer №2

When using ts-node in a project, it typically relies on the local tsconfig.json file, which may not be configured for execution purposes.

To override these default settings for ts-node, you can create a specific section in your tsconfig.json. In my case, specifying to build for esm has worked well:

{
  "compilerOptions": {
    ...
  },
  "ts-node": {
    "esm": true,
    "compilerOptions": {
      "module": "nodenext",
    }
  }
}

Answer №3

Perhaps you can try the following solution:

run the following command in your terminal: node --no-warnings --loader ts-node/esm file.ts

Answer №4

node --import "data:text/javascript,import {register} from 'node:module'; import {pathToFileURL} from 'node:url'; register('ts-node/esm', pathToFileURL('./'))" my-script.ts

Operational on Node.js v20.8.0+. 😢

...

You have the option to generate a file called ts-loader.js:

import {register} from 'node:module'
import {pathToFileURL} from 'node:url'

register('ts-node/esm', pathToFileURL('./'))

Then:

node --import ./ts-loader.js my-script.ts

Note: Avoid using the loader path as ts-loader.js (if the loader file is within your source). Instead, make sure you use the relative path: ./ts-loader.js like in your internal imports!

Downsides:

  1. It cannot resolve imports without extensions inside my-script.ts (as well as recursively in files imported in my-script.ts)! Therefore, all your imports must explicitly include .js extension (or potentially .ts extension if you set up allowImportingTsExtensions in your tsconfig.json).
  2. Additionally, you must not exclude /index.js//index.ts from the end of your paths!
  3. It does not handle jsx/tsx contents!
  4. Based on my tests, it does not adhere to the compilerOptions.paths configuration in your tsconfig.json. For instance, if you set something like
    "@/*": ["./src/*"]
    in your paths, then the above loader will fail to resolve @/... prefixed imports within my-script.ts (and in files directly or indirectly imported in it)!
  5. In the simple cases I tested, it was approximately twice as slow as the superior solution below utilizing esbuild:

Better alternative solution employing register()/--import of node.js v20.8+ and esbuild:

I devised this loader script for my projects:

register-ts-loader.js:

// Helpful links:  
// https://stackoverflow.com/a/68621282/5318303  
// https://github.com/nodejs/loaders-test/blob/main/typescript-loader/loader.js  
// https://github.com/nodejs/loaders-test/blob/main/commonjs-extension-resolution-loader/loader.js  
  
import {transform} from 'esbuild'  
import {readFile} from 'node:fs/promises'  
import {isBuiltin, register} from 'node:module'  
import {dirname, extname, posix, relative, resolve as resolvePath, sep} from 'node:path'  
import {fileURLToPath, pathToFileURL} from 'node:url'  

// Keep this loader towards the end of the chain.
register(import.meta.url, pathToFileURL('./'))

export async function resolve(specifier, context, nextResolve) {
  if (isBuiltin(specifier)) return nextResolve(specifier, context)
  // Remaining logic follows...

And then:

node --import ./register-ts-loader.js my-script.ts

without experiencing the aforementioned drawbacks. 😊

Don't forget npm i -D esbuild.
Also, refer to:


Check out my other response detailing new Node.js features related to --loader and newer --import + register():

UPDATE:

The tsx package presents another excellent solution, leveraging esbuild and certain new Node.js functionalities. It includes additional valuable features such as TypeScript REPL, shebang, etc.!

Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import when attempting to start Nodejs App locally


As an alternative, consider utilizing Bun.js with its built-in TypeScript support and various optimizations and features.

Answer №5

To include the CommonJS module, simply use the following command:

npx ts-node -O '{\"module\": \"commonjs\"}' db/initializers/inituser.ts

There is no requirement to specify

"type": "module"
in the package.json file anymore.

Answer №6

For those coming across this Stack Overflow question seeking guidance on how to utilize ts-node in VS Code without encountering the deprecation warning, here's a solution:

  1. Follow Mir-Ismaili's suggestion and create a .js file.
  2. In VS Code's launch.json, update or create a launch configuration that incorporates a runtimeArgs section like the one below:
    "configurations": [
        {
            "name": "Launch using ts-node",
            "request": "launch",
            "cwd": "${workspaceFolder}",
            "env": {
                "NODE_ENV": "development",
                "DEBUG": "wa_reminders:*",
                "DEBUG_COLORS": "true",
            },
            "runtimeArgs": [
                "--import",
                "./src/ts-loader.js"
            ],
            "args": [
                "${relativeFile}"
            ],
            "skipFiles": [
                "<node_internals>/**",
                "<node_modules>/**"
            ],
            "type": "node",
        },
        ...    
    ]

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

Executing service calls in a for loop in Angular 2 using the Http module

Encountered a challenge with Angular 2 HTTP service call within a for loop. The for loop executes quickly compared to the slow result returned by the service call. this.projectService.addProjectServices(pid, rid, vname, field_name, ser_name).subscribe( ...

import types dynamically in TypeScript

One of the files I have is called MyFactory.ts. Here is its content: export type CommandFactory = () => string[] | undefined; export enum FactoryIds {commandFactory : 'commandFactory'} Now, my goal is to dynamically import this file into anot ...

Error Encountered: Unable to access property 'cars' as it is undefined in Angular Material Table

I'm encountering an issue with the Angular Material Table (Angular Material Table) After using ng generate @angular/material:material-table --name=car-table to create the default angular table, everything works fine. However, when I attempt to injec ...

Splitting a string in Angular: A step-by-step guide

Is there a way to separate a string using the pipe symbol? The string I have is: Alex Santos||<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0968656c71277a68677d667a479871ab808a88878a">[email protected]</a> I on ...

Issue with React TypeScript: Only the first state update takes effect, despite multiple updates being made

Check out this sandbox I created here. When you leave any of the form inputs blank, I should be seeing 3 errors but instead, I only get one. Can anyone explain why this is happening? import React, { ChangeEvent, useState } from 'react'; import { ...

Using a function as a parameter in Typescript: Anticipated no arguments, received 1.ts

I'm encountering an issue when trying to pass the doSomething function into performAction. The error message I'm receiving is Expected 0 arguments, but got 1 interface SomeInterface { name: string, id: string } function doSomethingFunction( ...

The Typescript intellisense feature in VS Code seems to be malfunctioning

While setting up typings for my Node server, the intellisense suddenly stopped working. I checked my tsconfig.json file: { "version": "0.1.0", "command": "tsc", "isShellCommand": true, "args": ["-p", "."], "showOutput": "silent", " ...

Attempting to conceal certain elements based on the current route in Angular 5

Trying to create a dynamic navigation system where different items are displayed based on the website path. For example, if the path is http://mywebsite.com/path, certain navigation items should be hidden while others are shown. My current setup includes. ...

Unsure about module loading with system.js and navigating Typescript

I am currently in the process of transitioning an ASP.Net MVC application to Angular2, and I've encountered some perplexing behavior that I can't seem to grasp. Within my Angular2 app, I have a separate Layoutview that allows me to switch betwee ...

How can Typescript be leveraged to enforce a generic constraint on an interface?

I have defined 2 interface declarations : interface IStore { } interface AnotherInterface { a: number; } Also, there are 2 classes which implement each interface: class StoreImplementation implements IStore { } class AnotherImplementation implement ...

Creating a User-friendly Layout for Admin Pages in Next.js Version 13

Hey there, I'm facing an issue with the layout while using Next.js 13 Experimental App Directory. On my website's index page or routes '/', I want to show a landing page and use a specific layout for all pages except for those under the ...

How can a TypeScript Angular directive utilize a function?

Recently, I have been following a unique Angular directive TypeScript pattern that I find really effective. The approach involves giving the directive its own isolated scope by creating a new controller. I encountered a scenario where I needed to invoke a ...

Set up a server using Typescript and Node.js on the render.com platform

When attempting to deploy my TypeScript and Node.js application on render.com, I encountered the following error: `Jun 26 01:51:02 PM ==> Starting service with 'node app.ts' Jun 26 01:51:02 PM internal/process/esm_loader.js:74 Jun 26 01:51: ...

A collection of JSON data containing various diverse values

My classes are not specific and they look like this: type SyncReducerAction<TState> = (state: TState, ...args: any[]) => TState; type AsyncReducerAction<TState, TResult, TRest extends any[]> = { promise: (...args: TRest) => Promise< ...

Using Angular to incorporate HighCharts for a gauge chart

I'm currently working on an Angular project where I need to display a statistic using a gauge chart. The thing is, I'm utilizing the HighCharts library and it's worth mentioning that I've successfully used other types of charts from Hig ...

What is the best way to modify a button's color when it is clicked in Ionic2?

While testing on the Bluestacks Android simulator, I noticed that the natural responsiveness of Ionic buttons is not working as expected. I want to ensure that going forward, the button color changes when clicked. Should I achieve this with CSS or some ot ...

Ways to shift duplicates to the beginning of an Object array?

I am working with a variable that contains an array of objects let Obj1 = [ {Id: 123, name: 'A'}, {Id: 124, name: 'B'}, {Id: 125, name: 'C'}, {Id: 126, name: 'D'}, {Id: 127, name: 'E&apo ...

Identifying Typescript argument types

The given code is functional, but I am looking to refactor it for better clarity using Typescript syntax if possible. class Actions { actions: string[] } type Argument = object | Actions; export class GetFilesContext implements IExecutable { execute( ...

Listening for keypress events on a div element using React

I'm currently struggling with implementing a keypress listener on a component. My goal is to have my listener activated whenever the "ESC" key is pressed, but I can't seem to figure it out. The function component I am working with is quite stra ...

Determining the return type of a function through conditional types and signature overload

Exploring the usage of TypeScript 2.8's upcoming conditional types, I encountered an issue with my declaration of MockedImplementation<F>. This declaration is intended to encompass a full function matching F, the return type of F, and if the ret ...