I would like VSCode to IntelliSense the module path so I can access it by click.
For example, after configurating jsconfig.json I'm able to access ./src/styled/index by importing its global path.
But I couldn't figure out how to make it work with an alias #styles
// VSCode Intellisene Works
import { mixins, theme } from 'styles';
// VSCode Intellisene Doesn't work
import { mixins, theme } from '#styles';
My current jsconfig.json:
{
"compilerOptions": {
"baseUrl": "./",
"jsx": "react",
"paths": {
"#styles": ["src/styles/index"]
}
}
}
Seems I had to restart VSCode.
Javascript (javascript,javascriptreact file types in VSCode)
An example of jsconfig.json file for reference:
{
"compilerOptions": {
"baseUrl": "./src",
"jsx": "react",
"paths": {
"#styles": ["styles/index"],
"#fonts": ["fonts/index"],
"#components": ["components/index"],
"#atoms": ["components/atoms/index"],
"#molecules": ["components/molecules/index"],
"#organisms": ["components/organisms/index"],
"#templates": ["components/templates/index"],
"#icons": ["components/atoms/Icons/index"],
"#config": ["config/index"],
"#utils": ["utils/index"],
"#hooks": ["hooks/index"],
"#constants": ["constants/index"],
"#queries": ["queries/index"],
"#reducers": ["state/store/reducers"],
"#actions": ["state/store/actions"],
"#slices": ["state/slices/"],
"#storybookHelpers": ["../.storybook/helpers"]
}
}
}
An example of how styles/index looks like:
export * from './colors';
export * from './GlobalStyle.styles';
export * from './mixins.styles';
// Or
export { COLORS } from './colors';
export { default as GlobalStyle } from './GlobalStyle.styles';
export { default as mixins } from './mixins.styles';
Will allow import (with IntelliSense):
import { COLORS, mixins, GlobalStyle } from '#styles';
For a bonus: aliases.js, which is a helper which I use to define aliases in webpack config files, it helps to not repeat yourself, for example when using the same aliases in storybook and for the application itself.
// Remember to update `jsconfig.json`
const aliases = (prefix = `src`) => ({
'#actions': `${prefix}/state/store/actions`,
'#atoms': `${prefix}/components/atoms`,
'#molecules': `${prefix}/components/molecules`,
'#organisms': `${prefix}/components/organisms`,
'#templates': `${prefix}/components/templates`,
'#components': `${prefix}/components`,
'#config': `${prefix}/config`,
'#constants': `${prefix}/constants`,
'#hooks': `${prefix}/hooks`,
'#icons': `${prefix}/components/atoms/Icons`,
'#queries': `${prefix}/queries`,
'#reducers': `${prefix}/state/store/reducers`,
'#slices': `${prefix}/state/slices`,
'#styles': `${prefix}/styles`,
'#utils': `${prefix}/utils`,
'#storybookHelpers': `../.storybook/helpers`,
});
module.exports = aliases;
// usage example at .storybook/webpack.config.js file
const path = require("path");
const alias = require(`../src/config/aliases`);
const SRC = "../src";
const aliases = alias(SRC);
const resolvedAliases = Object.fromEntries(
Object.entries(aliases).map(([key, value]) => [
key,
path.resolve(__dirname, value),
])
);
module.exports = ({ config }) => {
config.resolve.modules.push(path.resolve(__dirname, SRC));
config.resolve.alias = resolvedAliases;
return config;
};
Typescript (typescript,typescriptreact files)
At tsconfig.json use the compilerOptions.paths option, notice that the paths are relative to baseUrl:
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"#components/*": ["components/*"],
"#config": ["config"],
"#constants": ["constants"],
"#hooks": ["hooks"],
"#styles": ["styles"],
"$types/*": ["types/*"],
"#utils": ["utils"]
}
}
This allows aliases (with IntelliSense), for example:
// Example of hooks/index.ts file
export * from './useLogin';
export * from './useLocalStorage';
export * from './useAuth';
// Usage examples
import {ROUTES} from '#constants';
import {Text} from '#components/atoms';
import {mixins} from '#styles';
import {useLocalStorage} from '#hooks';
In the settings.json file, add this line:
"typescript.preferences.importModuleSpecifier": "non-relative"
If this property is removed, then the ugly relative auto-import is the default option. Simply change 'typescript' to 'javascript' if you're currently using JS. To know more about this setting option, just hover on it like this:
(Bonus tip) Prefix #app/ to all import paths with the following compiler options in tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#app/*": ["./*"]
}
},
}
I had the right configuration as described by the other answers. In VS code I restarted the TypeScript server using Ctrl + Shift + P -> TypeScript: Restart TS server command and it fixed the editor highlighting the import path error.
Just for completeness here is what my tsconfig.json looks like:
{
"compilerOptions": {
...
"baseUrl": ".",
"paths": {
"#/*": ["./src/*"]
}
},
"include": ["src/**/*"]
}
As a side note, make sure the include in your jsconfig/tsconfig is pointing to correct paths.
For anyone like me who the other answers aren't working for, these are the tsconfig bits that worked for me, in addition to the settings addition in the accepted answer and ensuring you're setting includes/excludes properly:
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#/*": ["./src/*"],
}
}
Full credit to this gist: https://gist.github.com/EmilyRosina/eef3aa0d66568754a98382121fefa154
Related
Hi, I'm having this erreor while doing the Router view:
Cannot find module '#/src/views/HomeView.vue' or its corresponding type declarations.
I had tried different paths and had changed the tsconfig.vue file, but still get the error.
// tsconfig.json
{
"extends": "#vue/tsconfig/tsconfig.web.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#/*": ["./*"]
}
},
"references": [
{
"path": "./tsconfig.config.json"
}
]
}
// router/index.ts
import HomeView from '#/src/views/HomeView.vue'
import HomeView from '#/views/HomeView.vue'
const routes = {
'/': HomeView,
}
I would like to change import from ../../../db/index.js to db/index.js
I have already added this setting in my jsconfig.json but I still got this error.
{
"compilerOptions": {
"module": "commonjs",
"baseUrl": "src"
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules"
]
}
Finally found the right answer after trying different kinds of approaches.
Eslint import resolver and babel import resolver seem to be not working.
Add the ff:
package.json
"imports": {
"#root/*": {
"default": "./src/*"
}
},
If you want to access that import directy via ctr+click/left click create jsconfig.json
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"baseUrl": "./src",
"paths": {
"#root/*": ["./*"]
}
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules"
]
}
Usage in your index.js:
import level1 from '#root/level1/index.js';
instead of:
import level1 from './level1/index.js';
https://marian-caikovski.medium.com/4-ways-to-avoid-double-dots-in-module-specifiers-f5b6086cd9d1
These are two very different things:
import { something } from '../../something' - local import (file you've created)
import { something } from 'something' - import from a package (e.g. installed with yarn add something
If you'd like to clean up your imports and be able to do something like:
import { something } from '#components/something' then you need additional plugins/setup. It's worth looking into babel-plugin-root-import for example.
There might be other plugins/tools to do that but I've never had the need do do that so I don't know.
I am using svelte kit (with typescript) and have some created some shortlinks and cannot get the new link "$base" to work. I added the shortlink here
./jsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"baseUrl": ".",
"paths": {
"$lib": ["src/lib"],
"$lib/*": ["src/lib/*"],
"$base": ["src/baseApp"],
"$base/*":["src/baseApp/*"]
}
},
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
}
The is also no intellisense
More details about jsconfig.json here
I also found something about a similar issue with NEXT here
I tried this and it didn't work
In addition to jsconfig.json I tried adding my the paths to my tsconfig.json file also
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true
},
"paths": {
"$lib": ["src/lib"],
"$lib/*": ["src/lib/*"],
"Base": ["src/baseApp"],
"Base/*":["src/baseApp/*"]
}
}
Try adding your paths to the svelte.config.js file in the root of your project
...
import path from 'path';
/** #type {import('#sveltejs/kit').Config} */
const config = {
...
kit: {
...
vite: {
resolve: {
alias: {
$lib: path.resolve('./src/lib'),
$base: path.resolve('./src/baseApp'),
}
}
}
}
};
export default config;
Edit: Newer versions of sveltekit uses vite.config.js instead
import { sveltekit } from '#sveltejs/kit/vite';
import path from "path"
const config = {
resolve: {
alias: {
'$lib': path.resolve('./src/lib/'),
'$base': path.resolve('./src/baseApp'),
},
},
plugins: [sveltekit()]
};
export default config;
This is the latest way of implementing it. No need for vite config file
https://kit.svelte.dev/docs/configuration#alias
//svelte.config.js
import path from 'path';
const config = {
...
kit: {
...
alias: {
$components: path.resolve('./src/components')
}
}
};
In my nextjs project I have mapped path in jsconfig.json to make easy absolute imports
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"#/*": ["./*"]
},
"target": "es6",
"module": "commonjs",
"experimentalDecorators": true
}
}
My import paths look like this
import { VIEW } from '#/src/shared/constants';
My eslintrc.js has settings specified as
module.exports = {
... ,
settings: {
"import/resolver": {
alias: {
extensions: [".js"],
map: ["#", "."]
}
}
}
}
I am still getting the error saying can't resolve "#/what/ever/my/path/is"
How do I make eslint realize the jsconfig path
I was using babel-eslint as my parser in eslintrc. While searching, I realized I need to add babel-plugin-module-resolver in babelrc to resolve the modules. In this file we can define our mapped paths which are there in our jsconfig.
Hence adding the following plugin in the babelrc file compiled my code successfully.
[
"module-resolver",
{
"alias": {
"#": "./"
}
}
]
According to the docs for eslint-import-resolver-alias, the map property should be an array of arrays, so try this:
module.exports = {
... ,
settings: {
"import/resolver": {
alias: {
extensions: [".js"],
map: [ ["#", "."] ]
}
}
}
}
Also, double-check that you actually have eslint-import-resolver-alias installed - it's easy to forget!
I have this code in TS to create an instance of ConnectRoles Middleware in Express:
let user = new ConnectRoles(config);
this is what the middleware expects to be able to initialize, a simple call to a constructor, however after transpiling, the resulting javascript code looks like this:
let user = new connect_roles_1.default(config);
I am importing this class in TS using:
import ConnectRoles from "connect-roles";
which translates to:
const connect_roles_1 = require("connect-roles");
in JS, is it possible that the way in which I am instantiating/importing the class may be the issue here? I can remove manually the "default" method that is causing errors in the code in the JS, but this defeats the purpose of using a transpiler, specially if things like this start happening more often.
One more thing, this is my tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": { "*": ["types/*"] },
"target": "es2015",
"module": "commonjs",
"moduleResolution": "node",
"isolatedModules": false,
"jsx": "react",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"declaration": false,
"noImplicitAny": false,
"noImplicitUseStrict": false,
"removeComments": true,
"noLib": false,
"preserveConstEnums": true,
"suppressImplicitAnyIndexErrors": true,
"outDir": "app",
"sourceMap": true,
"watch": true
},
"exclude": [
"node_modules",
"typings/browser",
"typings/browser.d.ts",
],
"compileOnSave": true,
"buildOnSave": true,
"atom": {
"rewriteTsconfig": false
}
}
Any ideas will be very appreciated, thanks!
As Tobiq says, import ConnectRoles from "connect-roles" is trying to import a default export. The module you're trying to import does not use a default export, though; instead, it uses module.exports = ConnectRoles.
Here are three different import styles and the compiled results that they produce:
import ConnectRolesImport from 'connect-roles';
const connectRolesImport = new ConnectRolesImport(); // error!
import * as ConnectRolesImportAll from 'connect-roles';
const connectRolesImportAll = new ConnectRolesImportAll();
import ConnectRolesRequire = require('connect-roles');
const connectRolesRequire = new ConnectRolesRequire();
Compiled Result:
var connect_roles_1 = require("connect-roles");
var connectRolesImport = new connect_roles_1["default"]();
var ConnectRolesImportAll = require("connect-roles");
var connectRolesImportAll = new ConnectRolesImportAll();
var ConnectRolesRequire = require("connect-roles");
var connectRolesRequire = new ConnectRolesRequire();
Here is one of the TypeScript team members talking about the difference between the import xxx as... and import xxx = require... syntax. That and this answer's comments will help you choose which to use.
You should think of typescript files as modules, which export objects.
import {x, y, z} from "module" is how you access these exports.
When you use import x from "module", you're actually just importing the default from the module.
import x from "module" is simply an alias for import {default as x} from "module"
module itself isn't one export. Which is why you can also still import other exports:
import default, {x, y, z} from "module"
module.ts
export const x = /*...*/;
export const y = /*...*/;
export const z = /*...*/;
export const default = /*...*/;
In the past, you could export one default like so:
module.exports = /*...*/;
However, now you should think of exports strictly following the form:
{
exportName: /*...*/,
default: /*...*/
}
Many modules still use the old convention to export a default: module.exports = /*...*/;
In this case, you can import them using import * as x from "module";