Search code examples
typescriptmoduletsconfig

TypeScript src module imports aren't compiled correctly in dist


I'm developing a REST API in TS that, summarized, is structured in the following way:

├── dist
│   ├── index.js
│   ├── library.js
├── src
│   ├── index.ts
│   ├── library.ts
├── node_modules
├── package.json
├── package-lock.json
├── tsconfig.json
└── .gitignore

The issue that I'm facing is that module imports in index.ts are not being compiled correctly in index.js, as a reference:

index.ts

import { someFunc } from '../library.ts';

index.js

import { someFunc } from '../library.ts';

If the file were compiled correctly, index.js's imports would be:

import { someFunc } from '../library.js';

I think it's safe to say that the issue is related to tsconfig.json:

{
  "compilerOptions": {
    "module": "NodeNext",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "outDir": "dist",
    "allowImportingTsExtensions": true
  }
}

I have tried to play around with tsconfig.json but did not end up in finding a satisfying solution, I would also like to keep the module type set to NodeNext rather then ESNext.


Solution

  • tsc does not touch the import path (a.k.a. "module specifier"), including the potential file extension:

    the module specifier (the string from which you import, or pass to require) is always emitted as-written.

    You have to write the final file extension:

    // In index.ts
    import { someFunc } from '../library.js'; // Final .js file extension
    

    ...even if it means

    strangeness of seeing output file extensions in input files