Skip to content

Move to a new file doesn't add extension with "module": "nodeNext" leading to a broken importΒ #50710

Closed

Description

Bug Report

πŸ”Ž Search Terms

move to new file extension nodenext

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about extensions

⏯ Playground Link

N/A Only applies to multi-file refactoring

πŸ’» Code

// Refactor this function to a new file
function someLibFn(): string {
    return someOtherFn();
}

function someOtherFn(): string {
    return "hello world!";
}

console.log(someLibFn());

πŸ™ Actual behavior

The import generated is missing the .js extension.

i.e. This is generated:

import { someLibFn } from "./someLibFn";

Similarly in the other file the reverse import is also missing it's extension:

import { someOtherFn } from "./example";

This broken refactor produces a predictable TS error:

Relative import paths need explicit file extensions in EcmaScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './someLibFn.js'?ts(2835)

See also as video:

Screencast.from.11-09-22.00.10.49.webm

πŸ™‚ Expected behavior

It should generate with the .js extension as (and ditto for the other file):

import { someLibFn } from "./someLibFn.js";

Notes

This is almost certainly related to #46290 . However this doesn't really have anything to do with the vscode specific option importModuleSpecifierEnding, so I made a separate issue.

tsconfig.json

In case this issue is caused by a combination of settings here is the full tsconfig.json:

{
    "include": [
        "./**/*.ts",
        "./**/*.mts",
        "./**/*.cts"
    ],
    "exclude": [
        "./**/*.d.ts",
        "./**/*.d.mts",
        "./**/*.d.cts"
    ],
    "compilerOptions": {
        "composite": true,
        "declaration": true,
        "declarationMap": true,
        "downlevelIteration": true,
        "isolatedModules": true,
        "module": "NodeNext",
        "rootDir": "./",
        "sourceMap": true,
        "target": "esnext",
        "newLine": "lf",
        "useDefineForClassFields": true,
        "strict": true,
        "alwaysStrict": true,
        "exactOptionalPropertyTypes": true,
        "noImplicitOverride": true,
        "noUncheckedIndexedAccess": true,
        "importsNotUsedAsValues": "error",
        "forceConsistentCasingInFileNames": true
    }
}

Activity

  1. changed the title [-]Move to a new file doesn't add extension with "module": "nodeNext" leading to a broken module[/-] [+]Move to a new file doesn't add extension with "module": "nodeNext" leading to a broken import[/+] on Sep 10, 2022
  2. a-tarasyuk commented on Sep 13, 2022

    @a-tarasyuk
    Contributor

    Just curious, we have a TypeScript file/code and we want to move it to a new file (JavaScript file? πŸ˜• ) and import that code from the JavaScript file - am I right?

    /cc Andrew Branch (@andrewbranch)

  3. andrewbranch commented on Sep 13, 2022

    @andrewbranch
    Member

    It looks like both files are TypeScript from the screencast, but I don’t think it really matters.

  4. egasimus commented on Sep 19, 2022

    @egasimus
  5. added a commit that references this issue on Dec 6, 2022
  6. locked as resolved and limited conversation to collaborators on Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugA bug in TypeScriptDomain: LS: Refactoringse.g. extract to constant or function, rename symbolFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions