Skip to content

ERR_MODULE_NOT_FOUND using es modules #1777

Description

@Ziothh

Search Terms

ts-node, ERR_MODULE_NOT_FOUND

Expected Behavior

run my typescript es module files.

Actual Behavior

I have a project that looks like this

  • package.json
  • tsconfig.json
  • src/main.ts
  • src/module.ts

I have a "start" script in my package.json that I run via pnpm start that executes
ts-node ./src/main.ts. (I have also tried this with npm and it also didn't work)

When I run this I get the error "Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.". So I do as I'm told and I add it to my package.json and run it again.

Now I get this error: "TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for [path-to-project]/src/main.ts"

I manage to resolve this error by adding "--esm" to my start script like this: ts-node --esm ./src/main.ts. If I run my start script I get a new error: "Cannot find module '[path-to-project]/src/module' imported from [path-to-project]/src/main.ts"

I can surpass this error by doing this:

// main.ts
// -- 
import { myLog } from "./module"
// --
// ++ 
// ** Add a ts-ignore because typescript doesn't like me adding the file extension. */
// @ts-ignore
import { myLog } from "./module.ts"
// ++

Now my code runs but I have some issues with this

  • I don't like adding ".ts" behind every import. This defeats the purpose of auto-imports
  • Typescript really doesn't like me adding a file extension in an import statement.

How can I make my code work with ts-node by removing the ".ts" extension in the import statement?

Minimal reproduction

// main.ts
import { myLog } from "./module"

console.log("hiii")
myLog()
// module.ts
export const myLog = () => console.log("module imported")

Specifications

  • ts-node version: 10.8.0 | 10.7.0 (tried both versions)
  • node version: 16.15.0 | 18.2.0 (switched using nvm)
  • TypeScript version: 4.7.2
  • tsconfig.json:
{
    "compilerOptions": {
        "target": "ESNext",
        "module": "ESNext",
        "skipLibCheck": true,
        "sourceMap": true,
        "outDir": "./dist",
        "moduleResolution": "node",
        "removeComments": true,
        "noImplicitAny": false,
        "strictNullChecks": true,
        "strictFunctionTypes": true,
        "noImplicitThis": true,
        "noUnusedLocals": false,
        "noUnusedParameters": false,
        "noImplicitReturns": true,
        "noFallthroughCasesInSwitch": true,
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true,
        "experimentalDecorators": true,
        "allowJs": true,
        "emitDecoratorMetadata": true,
        "strict": false,
        "resolveJsonModule": true,
        "typeRoots": ["src/types", "./node_modules/@types"],
        "baseUrl": ".",
        "paths": {
            "@entities": ["src/entities/index.ts"],
            "@entities/*": ["src/entities/*"],
            "@config/*": ["src/config/*"],
            "@helpers/*": ["src/helpers/*"],
            "@mytypes/*": ["src/types/*"],
            "@server/*": ["src/server/*"]
        }
    },
    "exclude": ["node_modules"],
    "include": ["./src/**/*.ts"]
}
  • package.json:
{
    "type": "module",
    "devDependencies": {
        "@types/node": "^17.0.36",
        "ts-node": "10.7.0",
        "typescript": "^4.7.2"
    },
    "scripts": {
        "start": "ts-node --esm ./src/main.ts"
    }
}
  • Operating system and version: MacOS

Activity

  1. changed the title [-]ERR_MODULE_NOT_FOUND[/-] [+]ERR_MODULE_NOT_FOUND using es modules[/+] on May 29, 2022
  2. cspotcode commented on May 30, 2022

    @cspotcode
    Collaborator

    https://devblogs.microsoft.com/typescript/announcing-typescript-4-7/#type-in-package-json-and-new-extensions

    That section has a detailed breakdown of how file extensions work. I recommend reading it thoroughly. Remember that this is the way that TypeScript has chosen to do things, so ts-node follows along with those rules. Even if you are not using "module": "NodeNext", those rules still apply.

    Worth noting also that the --esm flag can be configured in your tsconfig.json if you prefer putting stuff in tsconfig instead of passing command-line flags. Your choice, whichever you prefer.

    When I run this I get the error "Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.".

    Can you copy-paste the complete terminal output that you see when getting this error? I suspect that there is additional context, perhaps some lines of output preceding or following that error. It will help to know what is giving you this error. I suspect node is giving it to you, but could also be typescript.

  3. Ziothh commented on May 30, 2022

    @Ziothh
    Author

    Thanks for the quick response.

    I've read the docs you sent me. So Node (& Typescript also) want you to always specify the file extension, right? Even though I've specified my module type in package.json.

    Visual Studio Code yells at me if I do this. It's running Typescript version 4.7.2
    The error: An import path cannot end with a '.ts' extension. Consider importing './module.js' instead.ts(2691).

    This error also also gets logged in the console if I run my files via ts-node
    Screenshot 2022-05-30 at 12 51 15

    I only manage to get my code working if I prepend my import statements with a "// @ ts-ignore"

    Can you copy-paste the complete terminal output that you see when getting this error? I suspect that there is additional context, perhaps some lines of output preceding or following that error. It will help to know what is giving you this error. I suspect node is giving it to you, but could also be typescript.

    Here are the errors I get before adding "type": "module"
    Screenshot 2022-05-30 at 12 55 24

    Worth noting also that the --esm flag can be configured in your tsconfig.json if you prefer putting stuff in tsconfig instead of passing command-line flags. Your choice, whichever you prefer.

    Thanks. I'll add it to my tsconfig

  4. cspotcode commented on May 30, 2022

    @cspotcode
    Collaborator

    My guess is you're still stuck putting a .ts extension in your import statements when you should put a .js extension instead. Try it even if it seems wrong; it'll work.

  5. Ziothh commented on May 31, 2022

    @Ziothh
    Author

    Sadly this works. Thanks for the help even though this isn't a ts-node problem but a typescript problem.

    It feels really wrong to put a ".js" extension behind my ts imports... I'm also bummed out that my auto imports don't auto add the extension.

    Hopefully I'll find some kind of import resolver that just adds the extension behind the scenes... For now switching to "module": "Node16 in my tsconfig does the job.

  6. cspotcode commented on May 31, 2022

    @cspotcode
    Collaborator

    Auto-imports can be configured to add the extension. There's a vscode setting for it; they also automatically mimic style of the other imports in the file.

  7. Ziothh commented on May 31, 2022

    @Ziothh
    Author

    Auto-imports can be configured to add the extension. There's a vscode setting for it; they also automatically mimic style of the other imports in the file.

    Alright I'll have a look.

  8. locked and limited conversation to collaborators on May 31, 2022
  9. converted this issue into a discussion #1781 on May 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions