TypeStrong / ts-node

TypeScript execution and REPL for node.js
https://typestrong.org/ts-node
MIT License
12.91k stars 534 forks source link

ts-node esm not working with package "type": "module" - Cannot find module #1833

Closed NikolayMakhonin closed 2 years ago

NikolayMakhonin commented 2 years ago

Search Terms

esm with package type module. CustomError: Cannot find module

TS2835, TS2691

Expected Behavior

It should work with es modules without errors.

Actual Behavior

C:\Users\Admin\AppData\Roaming\npm\pnpm.cmd test

> ts-node-issue@1.0.0 test D:\projects\-temp\ts-node-issue
> ts-node-esm src/index.ts

D:\projects\-temp\ts-node-issue\node_modules\.pnpm\ts-node@10.8.2_fxk5i3xm3ivo7fjwhcizcinpla\node_modules\ts-node\dist-raw\node-internal-modules-esm-resolve.js:366
    throw new ERR_MODULE_NOT_FOUND(
          ^
CustomError: Cannot find module 'D:\projects\-temp\ts-node-issue\src\test' imported from D:\projects\-temp\ts-node-issue\src\index.ts
    at finalizeResolution (D:\projects\-temp\ts-node-issue\node_modules\.pnpm\ts-node@10.8.2_fxk5i3xm3ivo7fjwhcizcinpla\node_modules\ts-node\dist-raw\node-internal-modules-esm-resol
ve.js:366:11)
    at moduleResolve (D:\projects\-temp\ts-node-issue\node_modules\.pnpm\ts-node@10.8.2_fxk5i3xm3ivo7fjwhcizcinpla\node_modules\ts-node\dist-raw\node-internal-modules-esm-resolve.js
:801:10)
    at Object.defaultResolve (D:\projects\-temp\ts-node-issue\node_modules\.pnpm\ts-node@10.8.2_fxk5i3xm3ivo7fjwhcizcinpla\node_modules\ts-node\dist-raw\node-internal-modules-esm-re
solve.js:912:11)
    at D:\projects\-temp\ts-node-issue\node_modules\.pnpm\ts-node@10.8.2_fxk5i3xm3ivo7fjwhcizcinpla\node_modules\ts-node\src\esm.ts:218:35
    at entrypointFallback (D:\projects\-temp\ts-node-issue\node_modules\.pnpm\ts-node@10.8.2_fxk5i3xm3ivo7fjwhcizcinpla\node_modules\ts-node\src\esm.ts:168:34)
    at D:\projects\-temp\ts-node-issue\node_modules\.pnpm\ts-node@10.8.2_fxk5i3xm3ivo7fjwhcizcinpla\node_modules\ts-node\src\esm.ts:217:14
    at addShortCircuitFlag (D:\projects\-temp\ts-node-issue\node_modules\.pnpm\ts-node@10.8.2_fxk5i3xm3ivo7fjwhcizcinpla\node_modules\ts-node\src\esm.ts:409:21)
    at resolve (D:\projects\-temp\ts-node-issue\node_modules\.pnpm\ts-node@10.8.2_fxk5i3xm3ivo7fjwhcizcinpla\node_modules\ts-node\src\esm.ts:197:12)
    at resolve (D:\projects\-temp\ts-node-issue\node_modules\.pnpm\ts-node@10.8.2_fxk5i3xm3ivo7fjwhcizcinpla\node_modules\ts-node\src\child\child-loader.ts:15:39)
    at ESMLoader.resolve (node:internal/modules/esm/loader:580:30)
 ELIFECYCLE  Test failed. See above for more details.

Process finished with exit code 1

Steps to reproduce the problem

Clone my repo and run npm test

Minimal reproduction

My repo is very minimal

Specifications

NikolayMakhonin commented 2 years ago

I added the .js extension to the import path and it worked.

import {test} from './test.js'

this is confused me, because js file is not exists, but tsc is worked and IDE code inspection is worked

NicolasThierion commented 2 years ago

I'm facing the same issue as well. I try to use ts-node --esm with a large existing codebase, and I don't want to add .js to each import.

Does anyone think of a possible solution ?

cspotcode commented 2 years ago

I don't want to add .js to each import.

Check out: https://nodejs.org/dist/latest-v18.x/docs/api/esm.html#mandatory-file-extensions https://nodejs.org/dist/latest-v18.x/docs/api/esm.html#customizing-esm-specifier-resolution-algorithm https://typestrong.org/ts-node/docs/options#experimentalspecifierresolution https://github.com/TypeStrong/ts-node/pull/1813/files#diff-8e9a64b8e2bd566ae76b953a77e069f6ca2ac0aa74af439287107aecfb42bb79R406

Many people will tell you to strongly consider adding .js to each import, but ultimately, the decision is yours to make.

bennycode commented 1 year ago

Thank you all for this workaround!

I just experienced the same problem (CustomError: Cannot find module) with ts-node v10.9.1 and ts-node-esm execution.

Changing my TypeScript import from import { getDistanceReport } from "./getDistanceReport"; to import { getDistanceReport } from "./getDistanceReport.js"; helped.

Because I found it weird to use a .js extension when importing a TS file, I decided to enable the allowImportingTsExtensions compiler flag. This at least allowed me to add a .ts extension.

Example:

import { getDistanceReport } from "./getDistanceReport.ts";
drake-nathan commented 1 year ago

I ran into this issue today as well. The .js solution works, but it's clearly not ideal. I am not sure if this is a bug with ts-node, or an issue with my repo. It's a large components repo that has a small node scripts section that I'm converting to TypeScript.

bennycode commented 1 year ago

I also thought that the .js extension solution isn't ideal but it is actually officially recommended:

relative import paths need full extensions (e.g we have to write import "./foo.js" instead of import "./foo") [...] bar.ts will instead have to import from ./foo.js. [...] This might feel a bit cumbersome at first, but TypeScript tooling like auto-imports and path completion will typically just do this for you.

Source: https://www.typescriptlang.org/docs/handbook/esm-node.html#type-in-packagejson-and-new-extensions

My .ts solution was not ideal as it only works with allowImportingTsExtensions which is only allowed when --noEmit or --emitDeclarationOnly is set. That being said, .js it is. 🌻

rolanday commented 1 year ago

I added the .js extension to the import path and it worked.

import {test} from './test.js'

this is confused me, because js file is not exists, but tsc is worked and IDE code inspection is worked

Thanks for the workaround! Non-obvious, and saves me from much uglier workaround.

pelly-ryu commented 1 year ago

There is new moduleResolution now: "bundler". ( https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#moduleresolution-bundler )

this might help some of you

i personally no more use ts-node but use vite-node currently tho..