Skip to content

rootDirs with Node16/NodeNext removes import extensions on file rename #50725

Closed
@esdmr

Description

@esdmr

Bug Report

🔎 Search Terms

rootDirs, file extension, Node16, Node12, NodeNext, module, moduleResolution, Classic, importModuleSpecifierEnding, importModuleSpecifier, auto-import, file move.

🕗 Version & Regression Information

The last change was between version 3.5 and 3.6: decc3cd, later in 4.7 it started to affect the Node16/NodeNext module resolution.

⏯ Playground Link

Not replicable in TypeScript Playground, as it requires file rename. Here is a fourslash test for it:

/// <reference path="fourslash.ts"/>

// @Filename: /tsconfig.json
////{
////  "compilerOptions": {
////    "module": "Node16",
////    "rootDirs": ["src"]
////  }
////}

// @Filename: /src/person.ts
////export const name = "John Doe";

// @Filename: /src/index.ts
////import {name} from "./person.js";

verify.getEditsForFileRename({
	oldPath: '/src/person.ts',
	newPath: '/src/vip.ts',
	newFileContents: {
		'/src/index.ts': 'import {name} from "./vip.js";',
	},
});

💻 Code

  1. Create a tsconfig.json setting moduleResolution to "Node16" and rootDirs to ["src"].
  2. Create src/a.ts and src/b.ts.
  3. Import './b.js' in src/a.ts.
  4. Try renaming src/b.ts. (Make sure to enable automatic import updating in your editor)

🙁 Actual behavior

TypeScript updates the filename, removing the extension as a result. In ESM this would then err that “File may not be imported without an extension”. (Also, it seems that typescript.preferences.importModuleSpecifierEnding is ignored.)

🙂 Expected behavior

The file extension should not be removed by TypeScript since the original import had it.

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptDomain: 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