Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

TypeScript imports with .js file extensions don't work #9358

Closed
justinfagnani opened this issue Nov 9, 2019 · 8 comments
Closed

TypeScript imports with .js file extensions don't work #9358

justinfagnani opened this issue Nov 9, 2019 · 8 comments
Labels
good first issue Easy to fix issues, good for newcomers Webpack Related to Webpack with Next.js.
Milestone

Comments

@justinfagnani
Copy link

Bug report

Describe the bug

When importing a TypeScript module from another, TypeScript allows the use of the .js file extension:

foo.ts:

export const foo = 42;

bar.ts

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

This is important in plain TypeScript projects because browsers don't do any module resolution and require the correct extensions. The compiled output works as it.

If you copy the same files into a Next.js project you will get a compile error that foo.js cannot be found.

To Reproduce

See above

Expected behavior

No compile errors

System information

  • OS: macOS
  • Version of Next.js: 9.1.2
@jeremy-coleman

This comment has been minimized.

@Timer Timer added this to the 9.1.x milestone Nov 9, 2019
@Timer
Copy link
Member

Timer commented Nov 9, 2019

Hey @justinfagnani! Thanks for letting us know about this issue.

I wasn't aware TypeScript allowed for this behavior. What happens when a .ts and .js version exist, do you know which it prefers?

Are there any other toolkits that support this behavior out-of-the-box? We'd love to see a reference implementation.

We'll explore the above questions if they're more nuanced when we get around to implementing this.

Feel free to send a PR as well!

@jeremy-coleman
Copy link

@Timer ts prefers ts and will ignore the js file when both are present, you can confirm with tsc -w without an outDir specified and changing the contents of the .js file - it won't recompile.

to get this working in next, i think https://github.com/tleunen/babel-plugin-module-resolver/blob/master/src/resolvePath.js has everything you need

@Timer Timer modified the milestones: 9.1.x, 9.2.x Jan 3, 2020
@lifeiscontent
Copy link
Contributor

seems that next.js prefers .ts files in node_modules folder over .js files as well, in a library I'm writing in TS which I build all my typescript files to js in the same folder, next.js starts crawling the node_modules directory for types and throws an error because I have a babel plugin that processes SVG and typescript doesn't know what it is.

@Timer Timer added good first issue Easy to fix issues, good for newcomers kind: story labels Jul 10, 2020
@Timer Timer modified the milestones: 9.x.x, backlog Jul 10, 2020
@PabloSzx
Copy link
Contributor

any news on this?

@timneutkens timneutkens added Webpack Related to Webpack with Next.js. and removed priority: p2 labels Nov 17, 2021
@samfortunato
Copy link

samfortunato commented Nov 28, 2021

👍 ing the importance of this issue. Not sure how strictly Next.js uses the feature request label, but I would argue that this should be expected behavior, not an added feature:

As an aside, some devs may have settings in their IDEs that auto-add .js to the end of their imports, to easily use ECMAScript modules/support the new spec. Modifying IDE config or dev workflow to go against spec for one library is not a good dev experience.

@dzek69
Copy link

dzek69 commented Nov 28, 2021

If anyone is looking for copy-paste workaround here it is:

  1. install babel-plugin-module-resolver (at the time of writing im using 4.1.0)

  2. create babel.config.js (if you already have it you will have to adjust it of course) and put this inside:

const path = require("path");
const fs = require("fs");

module.exports = {
    presets: ["next/babel"],
    plugins: [
        [
            "module-resolver",
            {
                extensions: [".js", ".jsx", ".es", ".es6", ".mjs", "ts", "tsx"],
                resolvePath(sourcePath, currentFile, opts) {
                    if (!sourcePath.startsWith("./") && !sourcePath.startsWith("../")) {
                        return sourcePath;
                    }

                    if (sourcePath.endsWith(".js")) {
                        const relPath = path.resolve(path.dirname(currentFile), sourcePath);
                        const tsPath = relPath.replace(/\.js$/, ".ts");
                        const tsxPath = relPath.replace(/\.js$/, ".tsx");
                        if (fs.existsSync(tsPath)) {
                            return tsPath;
                        }
                        if (fs.existsSync(tsxPath)) {
                            return tsxPath;
                        }
                    }

                    return sourcePath;
                },
            },
        ],
    ],
};

I'm using that for few months already without any issues.

I'd love to have this working without a workaround though. @samfortunato gave some nice arguments why.

@samfortunato
Copy link

@dzek69 Awesome, that did work. Was looking for a solution like this before.

Unfortunately, it means Next.js will not use the new Rust compiler. Would have to look at the SWC docs to see if a workaround could be configured in the same way...

@vercel vercel locked and limited conversation to collaborators Dec 7, 2021
@balazsorban44 balazsorban44 converted this issue into discussion #32237 Dec 7, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
good first issue Easy to fix issues, good for newcomers Webpack Related to Webpack with Next.js.
Projects
None yet
Development

No branches or pull requests

8 participants