Related
I am aware that this question has been asked multiple times however after trying most of them I am unable to make it work for my use case. I am building simple API with Typescript and Node. I have all my code residing in the src folder from the root.
To avoid those annoying ../../ i have configured absolute paths in my tsconfig.json with the following declarations.
"baseUrl": "./",
"paths": {
"*":[
"./src/*"
]
},
So lets say i have a config.ts file, I should be able to access it from 'src/controllers/tickets.controllers.ts' by just calling import config from 'config'
This does not work.
Additionally in my .eslintrc.json file i have added the following declarations as mentioned in many any answers related to this question.
{
"env": {
"es2021": true,
"node": true
},
"extends": [
"airbnb-base"
],
"parser": "#typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": [
"#typescript-eslint"
],
"rules": {
"import/extensions": [
"error",
"ignorePackages",
{
"js": "never",
"ts": "never"
}
]
},
"settings": {
"import/resolver": {
"node": {
"extensions": [
".js",
".ts"
]
}
}
}
}
I am trying to run on desktop this repository a vscode extension.
I cloned it locally and run npm install
Press f5 on vscode editor and got an error
Process exited with code 1
(node:1404) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
internal/process/warning:44
Canceled
To work around with the warning I found another stackoverflow question -
(node:9374) Warning: To load an ES module, set "type": "module"
So I set "type":"module" on package.json and press f5 again.
and another error show up.
Process exited with code 1
Uncaught TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /mnt/c/vscode-php-debug/src/phpDebug.ts
And found another question on stackoverflow - Can't run my Node.js Typescript project TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /app/src/App.ts
So I remove "type":"module" what happens is I'm in the loop now, confuse.
Does anyone tried debugging this or encounter as such?
Using the following command worked for me with node v14.16.1:
node --loader ts-node/esm --experimental-specifier-resolution=node index.ts
There is a warning telling me that --experimental-loader is an experimental feature but I don't care because I only use it to debug the typescript code.
setting "type": "module" in your package.json should work. Check again if you made an error in inputting it. Solved my problem when I inputted it.
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.
{
"version": "0.2.0",
"configurations": [
{
"type": "pwa-node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"cwd": "${workspaceFolder}",
"program": "${workspaceFolder}/index.js",
"runtimeArgs": ["-r","esm"],
}
]
}
Add
"module": "commonjs"
in tsconfig.json. This will resolve this issue
For more details refer: https://nodejs.org/api/modules.html#modules-commonjs-modules
Add "type": "module" in package.json file.
To fix this change the extension file name.
For example, if your module javascript file was called script.js - change the name to script.mjs.
Do this for both the file that will use the import and the file that will export.
Also in the index.html page ensure that you refer to the file using the .mjs extension for example:
<script type="module" src="script.mjs"></script>
Hello I would like to configure Typescript with composite config and webpack (the code was working well when using a single tsconfig.json). I precise that I am TypeScript newbie and rusted in javascript. I have difficulties to obtain my outputs json files.
EDIT: I added a bit more configuration and changed the directory structure for something better I believe
My project structure:
tsconfig.base.json
tsconfig.json
tsconfig.base.json
webpack.config.json
|--model
|--tsconfig.json
|--src
|--foo
|--x.ts
|--...
|--bar
|--y.ts
|--...
|--...
|--control
|--tsconfig.json
|--src
|--eventHandlerA.ts
|--eventHandlerB.ts
|--...
|--app1
|--tsconfig.json
|--src
|--app1.ts
|--app1
|--tsconfig.json
|--src
|--app2.ts
My desired output are 2 files "app1.js" and "app2.js". Both of them rely on a "controller" package which relies on a "model" package.
I would like to run at least the following commands:
npm run build #builds the javascript (can be reused for unit testing and package)
npm run package #builds and copy the output app1.js and app2.js in a delivery directory. I must be able to include only those js files to run my application in a webpage.
Content of ./tsconfig.js:
{
"references": [
{
"path": "app1"
},
{
"path": "app2"
}
],
"include": []
}
Content of ./tsconfig.base.js:
{
"compileOnSave": true,
"compilerOptions": {
"composite": true
"declaration": true,
"moduleResolution": "node",
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es6",
"jsx": "react",
}
}
Content of /tsconfig.js:
{
"files": [],
"include": [],
"references": [
{
"path": "app1"
},
{
"path": "app2"
}
]
}
Content of ./webpack.conf.js
module.exports = {
mode: "production",
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".ts", ".tsx"],
},
module: {
rules: [
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: [
{
loader: "ts-loader"
}
]
},
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader"
}
]
},
// When importing a module whose path matches one of the following, just
// assume a corresponding global variable exists and use that instead.
// This is important because it allows us to avoid bundling all of our
// dependencies, which allows browsers to cache those libraries between builds.
externals: {
"react": "React",
"react-dom": "ReactDOM"
}
};
content of package.json
{
"name": "abc",
"version": "1.0.0-SNAPSHOT"
"scripts": {
"test": "npm run build && jest",
"build": "tsc -b",
"clean": "tsc -b --clean",
"rebuild": "npm run clean && npm run build"
},
"keywords": [],
"author": "toto",
"license": "ISC",
"devDependencies": {
...
},
"dependencies": {
...
}
}
If I run npm run build, I have import failures. To analyze it I ran /tsc -b control/:
error TS2307: Cannot find module 'x' or its corresponding type declarations.
4 import * as x from 'x'
I tried to modify my import in several ways but I always have a failure on the import.
How to import a class (which is exported) from a composite "project" to another using absolute path?
Thank you for helping
To use absolute paths try to configure your tsconfig.json file with baseUrl and paths:
{
"compileOnSave": true,
"compilerOptions": {
"declaration": true,
"moduleResolution": "node",
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es6",
"jsx": "react",
"baseUrl": "../../", /// <--- baseUrl gives a path from the tsconfig to the root
"paths": {
"src/*": [ "../../src/*" ] /// <--- paths specify src/* is inside the src folder, which is ../../ relative to the tsconfig
}
},
"include": [
"./**/*.ts",
"./**/*.tsx"
]
}
I'm working on an EmailModule that reads a pug template.
I couldn't get the build to include the *.pug templates file:
I have followed the instruction based on this:
https://github.com/nestjs/nest-cli/issues/320
Adding the assets property in nest-cli.json
"email": {
"type": "library",
"root": "libs/email",
"entryFile": "index",
"sourceRoot": "libs/email/src",
"compilerOptions": {
"tsConfigPath": "libs/email/tsconfig.lib.json"
},
"assets": ["**/*.pug"]
},
The assets property should be inside the compilerOptions property
"email": {
"type": "library",
"root": "libs/email",
"entryFile": "index",
"sourceRoot": "libs/email/src",
"compilerOptions": {
"tsConfigPath": "libs/email/tsconfig.lib.json",
"assets": ["**/*.pug"]
}
},
This is bug with old nest-cli versions. I just updated this package to "#nestjs/cli": "^8.2.5", and everything worked fine with copying folders/subfolders/files.
The version 13.2 of Node.js allows ESM modules and a new package.json field, called exports, to select and rewrite exported files.
Before 13.2, I was importing files from the dist folder of my library with:
import myfile from 'mylibrary/dist/myfile'
With 13.2, I added this to my package.json:
exports: {
"./": "./dist/"
}
And tried to import files with:
import myfile from 'mylibrary/myfile'
But Typescript raises the 2307 error, saying that module is not found.
It is an upcoming feature of Typescript 4.5 which soon should be available:
// package.json
{
"name": "my-package",
"type": "module",
"exports": {
".": {
// Entry-point for `import "my-package"` in ESM
"import": "./esm/index.js",
// Entry-point for `require("my-package") in CJS
"require": "./commonjs/index.cjs",
// Entry-point for TypeScript resolution
"types": "./types/index.d.ts"
},
},
// CJS fall-back for older versions of Node.js
"main": "./commonjs/index.cjs",
// Fall-back for older versions of TypeScript
"types": "./types/index.d.ts"
}
For now, I've managed to utilize typesVersions:
"main": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": "./dist/index.js",
"./svg": "./dist/svg.js",
"./html": "./dist/html.js",
"./package.json": "./package.json"
},
"typesVersions": {
"*": {
"svg": ["dist/svg.d.ts"],
"html": ["dist/html.d.ts"]
}
}
There is some work required on the TypeScript side to support this. The feature is tracked here in github.
In that link there are also some workarounds listed.
For anyone else stumbling here after a seemingly endless odyssey of frustration and confusion:
Important:
Node Package Imports are supported only when moduleResolution
is set to "nodenext" or "node16".
tsconfig.json
{
"compilerOptions": {
// ∨
"moduleResolution": "nodenext"
// <... config>
}
}
If that's set, it'll work without a hitch. An example of how this may look in a project:
package.json
{
"type": "module",
"imports": {
"#util.define": "./src/util/define.ts"
// <... etc.>
}
// <... config>
}
main.ts
import * as define from '#utils.define'
class Main {
static {
define.symbol(Main.prototype, Symbol.toStringTag, "Main")
}
// <... etc.>
}
Building off the other answers, this block in my package.json worked for me:
{
// ...
"files": [
"/dist"
],
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": "./dist/index.js",
"./types": "./dist/types/index.js",
"./generate": "./dist/generate/index.js"
},
"typesVersions": {
"*": {
"types": [
"./dist/types/index.d.ts"
],
"generate": [
"./dist/generate/index.d.ts"
]
}
}
}
My tsconfig.json looks like this:
{
"extends": "#tsconfig/node14/tsconfig.json",
"include": ["src/**/*"],
"compilerOptions": {
"lib": ["es2020", "dom"],
"declaration": true,
"outDir": "dist",
"module": "ESNext"
}
}
And this is my file structure:
package.json
tsconfig.json
dist/ // and all its subfolders
src/
generate/
index.ts
types/
index.ts
index.ts
Separately, I'm using TypeScript 4.7.4. Supposedly the exports field is supported with this version, but it didn't work for me. But this (maybe overly complex) workaround worked for me.