Faced this and lots of connected issues during migrating from js (with commonJs modules) to Typescript with support of Eslint and Prettier. The main problem is that Node.js need commonJs imports in .js files and allow to use es6modules in .mjs. Typescript by default generates .js files, so there are 2 ways to handle it:
Way 1 (if you want to compile your ts files to js with es6modules support):
- Migrated to es6 modules, called all
.js
files - .mjs
, change __dirname
usages to const __dirname = dirname(fileURLToPath(import.meta.url));
- Then i set
"type": "module"
in package.json
- Then i added such config for tsconfig.json:
{
"compilerOptions":
{
"target": "es2018",
"module": "es2020",
"outDir": "dist",
"sourceMap": true,
"allowJs": true,
"esModuleInterop": true,
"moduleResolution": "node",
"strict": true,
},
"include": ["./src"],
"exclude": ["node_modules"],
}
- Config for .eslintrc.json looks like that:
{
"root": true,
"env": {
"es2020": true,
"jasmine": true,
"jest": true,
"node": true
},
"settings": {
"noInlineConfig": true,
"node": {
"tryExtensions": [".js", ".ts", ".d.ts"],
"moduleDirectory": ["node_modules", "src/"]
},
"import/resolver": {
"node": {
"extensions": [".js", ".ts", ".d.ts"],
"moduleDirectory": ["node_modules", "src/"],
"typescript": {}
},
"typescript": {
"alwaysTryTypes": true,
"project": "."
}
}
},
"parser": "@typescript-eslint/parser",
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:node/recommended",
"airbnb-base",
"prettier"
],
"parserOptions": { "ecmaVersion": 2018, "sourceType": "module" },
"plugins": [
"@typescript-eslint"
],
"rules": {
"import/extensions": "off",
"linebreak-style": "off",
"node/no-unsupported-features/es-syntax": "off",
"no-underscore-dangle": "off",
"import/prefer-default-export": "off",
}
}
- In one terminal i run :
npx tsc -w
- In another:
npm run start
Start script: "start": "nodemon --es-module-specifier-resolution=node dist/server.js"
Way 2 (if you don't care about compiled js code and it can be commonJS):
- Migrated to es6 modules, called all
.js
files - .ts
, add types, leave __dirname
usages as is (will be handled by @types/node) and install @types/node, ts-node, nodemon.
- In package.json
"type": "commonjs", "main": "src/{your_root_file}.ts",
- Then i added such config for tsconfig.json:
{
"compilerOptions":
{
"target": "es6",
"module": "commonjs",
"outDir": "dist",
"esModuleInterop": true,
"lib": ["es6"],
"moduleResolution": "node",
"strict": true,
"noEmitOnError": true,
"noImplicitAny": true,
"experimentalDecorators": true, // for typeorm
"emitDecoratorMetadata": true // for typeorm
},
"include": ["./src"],
"exclude": ["node_modules"],
}
- Config for .eslintrc.json looks like that:
{
"root": true,
"env": {
"es2020": true,
"jasmine": true,
"jest": true,
"node": true
},
"settings": {
"noInlineConfig": true,
"node": {
"tryExtensions": [".js", ".ts",".mjs", ".d.ts"],
"moduleDirectory": ["node_modules", "src/"]
},
"import/resolver": {
"node": {
"extensions": [".js", ".ts", ".d.ts", ".mjs"],
"moduleDirectory": ["node_modules", "src/"],
"typescript": {}
},
"typescript": {
"alwaysTryTypes": true,
"project": "."
}
}
},
"parser": "@typescript-eslint/parser",
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:node/recommended",
"airbnb-base",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:import/typescript",
"prettier"
],
"parserOptions": { "ecmaVersion": 2018, "sourceType": "module", "project": "./tsconfig.json" },
"plugins": [
"@typescript-eslint",
"eslint-plugin-tsdoc",
"import"
],
"rules": {
"tsdoc/syntax": "warn",
"import/extensions": "off",
"linebreak-style": "off",
"node/no-unsupported-features/es-syntax": "off",
"no-underscore-dangle": "off",
"import/prefer-default-export": "off",
"@typescript-eslint/no-explicit-any": "error",
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
}
- In terminal:
npm run start
Start script: "start": "nodemon src/server.ts"
Nodemon will automatically detect that it is running on .ts file and will use ts-node to run your application.