Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES import of typescript with .js extension fails #64

Open
janus-reith opened this issue Jan 3, 2022 · 11 comments
Open

ES import of typescript with .js extension fails #64

janus-reith opened this issue Jan 3, 2022 · 11 comments

Comments

@janus-reith
Copy link

janus-reith commented Jan 3, 2022

I'm using swc/node in ts-node to strip typings from my nodejs codebase using their ts-node/esm loader.
To keep tsc happy while also following the esm spec to keep the extension of all my imports, all my imports end as .js despite the source files being ts.

While this works for both tsc and ts-node with swc, all Jest tests fail due to imports of .ts files with .js that can't be resolved. I took the necessary steps to make Jest work with ESM, which used to work until I introduced TS there. Likewise, the tests work if I specify the ts extension for each of these imports, which would however break tsc.

I'm currently failing to fit the pieces together and have a hard time finding documentation or maybe a simple example that utilizes Node with ESM, SWC and imports ts files in a test suite.

I would also be happy to follow the Deno approach and explicitely keep the actual .ts extension on imports - However, I don’t know how I would typecheck my code then without tsc.

@janus-reith
Copy link
Author

The @swc/jest repo, which exists specifically for jest, even mentions using Jest with ESM, however that simply won't work once I actually want to type-check my code (Which I would still need tsc for)

Right now my best bet is to actually keep the explicit .ts imports, which I prefer anyways, and to fork tsc to disable that .ts file import error, similar to how Deno does it.
However I can't believe this is the only available option?

@janus-reith
Copy link
Author

This seems to be related: swc-project/swc#3043

@ewized
Copy link

ewized commented Jan 9, 2022

What does your config look like? You might have to tell @swc/jest to transform the files in node_modules by setting transformIgnorePatterns to an empty array.

module.exports = {
  extensionsToTreatAsEsm: ['.ts', '.tsx'],
  transformIgnorePatterns: [],
  testEnvironment: 'node',
  transform: {
    '^.+\\.(t|j)sx?$': '@swc/jest',
  },
};

@janus-reith
Copy link
Author

You might have to tell @swc/jest to transform the files in node_modules by setting transformIgnorePatterns to an empty array.

Thanks for the suggestion @ewized.
No, all of my modules which are distributed as ESM are already listed there to be ignored. (That part of the setup also works for me with Jest in ESM Mode)

What fails is the import of my actual source files which are about to be tested if they are .ts files and .js is specified in the import ( As demanded by Typescript for now🙄).

@Mad-Kat
Copy link

Mad-Kat commented Feb 4, 2022

I have exactly the same problem. Everything works with SWC and imports specified with the additional .js despite being typescript files. But the import mechanism fails when using jest 🤔

@Mad-Kat
Copy link

Mad-Kat commented Feb 4, 2022

In case you stumble upon this. I could fix the issue with the help of the ts-jest docs.

You need to add

module.exports = {
  moduleNameMapper: {
    '^(\\.{1,2}/.*)\\.js$': '$1',
  },
}

to your jest.config.js in order that Jest transforms the import statement correctly.

@janus-reith
Copy link
Author

Thanks @Mad-Kat, will give that a try!

@simonhammes
Copy link

In case you stumble upon this. I could fix the issue with the help of the ts-jest docs.

You need to add

module.exports = {
  moduleNameMapper: {
    '^(\\.{1,2}/.*)\\.js$': '$1',
  },
}

to your jest.config.js in order that Jest transforms the import statement correctly.

I also had to add this. Can this get added to the README and/or the docs?

@eric-burel
Copy link

eric-burel commented Oct 3, 2022

Related issue at Storybook: storybookjs/storybook#15962
Their solution use a webpack plugin that probably does something similar.

Just to clarify, having ".js" extension in a TypeScript barrel file (an index that reexport internal modules) sounds weird but seems a normal pattern when working with ESM. So if Storybook or Jest doesn't accept that, the solution is indeed to tweak Storybook or Jest configuration, not the source code of the app or library.

@Mad-Kat approach seems to work also with pure Jest, not using SWC

@patricklafrance
Copy link

patricklafrance commented Mar 1, 2023

Hey @Mad-Kat, how did you made SWC imports specified with the additional .js extension works outside of Jest?

I keep getting a "Module not found error" whenever I add a .js extension to any import.

Thank you 🙏🏻

Here's my config:

{
    jsc: {
        parser: {
            syntax: "typescript",
            tsx: true
        },
        target: "es2022",
        baseUrl: ".",
        paths: {
            "@host/*": ["src/*"]
        }
    },
    module: {
        type: "es6"
    },
    sourceMaps: true
}

UPDATE:

Found out that my issue is related to how Webpack handles import with file extensions (I am using swc-loader) rather than SWC cli.

@IdrisAkintobi
Copy link

The below works for me in my Node.js backend project. The rule applies to relative imports starting with a period (.) or double periods (..)

"moduleNameMapper": {
        "@src/(.*)": "<rootDir>/src/$1",
        "^(\\./.+|\\../.+).js$": "$1"
    }

OR

"moduleNameMapper": {
        "@src/(.*)": "<rootDir>/src/$1",
        "^(..?/.+).js?$": "$1"
    },

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

7 participants