I have a React Typescript project that has multiple files that share a structure. The code is similar, but quite different between them at some points, and it's pretty common to have to copy-paste files and change bits of information to create some of those new files.
I wanted to create a Node script that, asking the user for some input, would do that automatically. As I don't want to create a package for this (as it's a simple script inside my current project), I just created a folder called scripts
and put it there.
So, the project structure is as follows:
- node_modules/
- scripts/
- myScript/
- helpers/
- index.ts
- package.json
- ...
- src/
- tsconfig.json
- package.json
To be able to execute Typescript, I've installed the ts-node
library, and I'm executing this script through an npm script
in the main project's package.json
:
"run-script": "ts-node ./scripts/myScript"
This project already has code inside its src
folder, and this scripts
folder is a complement that does not belong to the main application's code, and that's why I keep it separated in an external folder, as it acts more as a helping tool for developers in the team.
Whenever I try to make an import, I get this error:
throw new ERR_MODULE_NOT_FOUND(
^
CustomError: Cannot find module ...
If I use dynamic imports for packages and set esModuleInterop
in my tsconfig
file, everything works fine. But as soon as I try to import a method with a relative path, it breaks:
const inquirer = (await import('inquirer')).default;
const fs = (await import('fs-extra')).default;
const { getCommonPath } = await import('./helpers/getCommonPath');
Error [ERR_MODULE_NOT_FOUND]: Cannot find module ...
I thought that could have to do with the directory path, but if I use __dirname
in the import, it tells me it's not allowed because of the format of the path.
If I try to use non-dynamic imports in stead, I get the following error:
(node:106220) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
But if I do that, then I get this error:
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for ...
Then I thought that would have to do with ts-node
configuration, and I read to use ts-node-esm. But if I do that, then the first error appears again. I've also tried multiple configurations for ts-node
(esModuleInterop: true
, esm: true
, module: CommonJS|ES2020|ESNext
...) without luck.
What do I have to do to be able to write a Node script with Typescript that I can execute from a command line that allows imports of both, external libraries and relative paths (that can be Typescript aswell)?
Thank you!
Actually I've been able to make it work finally with normal imports. Steps I've followed. I've followed the documentation of ts-node esm:
ts-node
package.package.json
inside the scripts
folder and set the "type": "module"
.tsconfig.json
: "ts-node": {
"transpileOnly": true,
"compilerOptions": {
"module": "ESNext",
"esModuleInterop": true
},
"esm": true // <--- this is the most important part
},
"compilerOptions": {...}
import fs from 'fs-extra';
import { getSrcPath } from './helpers/getSrcPath.ts';
ts-node
in your package.json
:"run-my-script": "ts-node ./scripts/myScript"