TS Config nested alias for absolute path not working - reactjs

I'm trying to set up path aliases in my tsconfig.json for a React app bundled with Vite. Here is the relevant part of my tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
...
"paths": {
"*": ["src/*", "node_modules/*"],
"components/*": ["src/components/*"],
"containers/*": ["src/containers/*"],
"pages/*": ["src/constants/*"],
"store/*": ["src/store/*"],
"types/*": ["src/types/*"],
"NestedFolder/*": [
"src/components/NestedFolder/*"
],
}
},
"include": ["src/**/*", "*"]
}
The only issue is with the NestedFolder. When I import this way, everything works:
import { ComponentName } from "components/NestedFolder/types";
However, the nested alias fails:
import { ComponentName } from "NestedFolder/types";
// error
EslintPluginImportResolveError: typescript with invalid interface loaded as resolver
Occurred while linting .../src/components/NestedFolder/canvas/index.ts:1
Rule: "import/namespace"
// error on hover in VS Code
Unable to resolve path to module 'NestedFolder/types'.eslintimport/no-unresolved
I would like to do nested components because I have several folders that are nested 3-4 levels and it would be nice to have a cleaner view of my imports. Is there a way to do this?

You need to install the vite-tsconfig-paths plugin to set up path aliases using TypeScript and Vite.
If nothing changes and you are using VSCode make sure to restart the TypeScript server by pressing Ctrl+Shift+P or Cmd+Shift+P, typing restart, and then selecting the command: TypeScript: Restart TS server

The accepted answer did not work for me. I found that I had to install the following packages:
npm i eslint-plugin-import eslint-import-resolver-alias eslint-import-resolver-typescript
And then add the following configurations, with the important ingredient being strongly-defined alias paths:
const path = require('path');
module.exports = {
root: true, // important to ensure nested eslint scoping in monorepos
plugins: ['#typescript-eslint', 'import'],
extends: [
'airbnb-typescript-prettier',
'plugin:import/typescript'
],
parser: '#typescript-eslint/parser',
parserOptions: {
project: path.join(__dirname, './tsconfig.json'),
tsconfigRootDir: './src',
},
settings: {
"import/parsers": { // add this definition
"#typescript-eslint/parser": [".ts", ".tsx"],
},
'import/resolver': {
alias: {
map: [
// define each alias here
['components', path.join(__dirname, './src/components')],
],
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json']
},
typescript: {
project: path.join(__dirname, './tsconfig.json'),
},
},
},
}
I think this could be improved on by harmonizing the aliases between the .eslintrc and vite.config so aliases only need to be defined once, using a tactic like the one defined here: https://stackoverflow.com/a/68908814/14198287

if vite-tsconfig-paths is not working for you. Make sure you didn't install v4.0.0. That version has a bug.
v4.0.1 fix it.
Install with the following:
npm install vite-tsconfig-paths#latest
Should install v4.0.1 at least.

I think this could be improved on by harmonizing the aliases between the .eslintrc and vite.config so aliases only need to be defined once, using a tactic like the one defined here: https://stackoverflow.com/a/68908814/14198287

Related

storyshots error - Could not locate module ./src/common mapped as

I have just installed #storybook/addon-storyshots and followed their instruction to put it at the root.
src/Storyshots.test.ts
import initStoryshots from '#storybook/addon-storyshots';
initStoryshots();
When I run tests, all my existing tests pass but it fails on this file - StoryShots.test.ts with error:
Error:
FAIL src/Storyshots.test.ts
Test suite failed to run
Configuration error:
Could not locate module ./src/common mapped as:
C:\apps\vanilla\storybook-examples\src\$1.
Please check your configuration for these entries:
{
"moduleNameMapper": {
"/src\/(.*)/": "C:\apps\vanilla\storybook-examples\src\$1"
},
"resolver": undefined
}
at createNoMappedModuleFoundError (node_modules/jest-resolve/build/index.js:552:17)
at Object.<anonymous> (node_modules/shelljs/shell.js:9:14)
I do have module resolution going on in my project and everything works there. See example module resolution for my project:
tsconfig.json
{
...
"compilerOptions": {
"baseUrl": "./",
},
"include": [
"src/**/*", "#types", "stories"
]
}
.babelrc
{
"plugins": [
...
["module-resolver", {
"extensions": [".js", ".jsx", ".ts", ".tsx"],
"root": ["./"],
"alias": {
"src": "./src"
}
}]
]
}
webpack.config.dev.js
const src = path.join(__dirname, '/src');
module.exports = {
...
resolve: {
modules: [src, 'node_modules'],
extensions: ['.ts', '.tsx', '.js', '.jsx', '.scss'],
// fix module resolver for typescript !!!
alias: {
src
}
},
I just haven't set any of these in .storybook folder - .storybook/. I'm not sure how storybook resolution works or why its looking for common/ folder. I have no common folder.
This is an example of one of my stories:
Basic.stories.tsx
import React from 'react';
import Basic from 'src/Components/Basic/Basic';
export const BasicHelloWorld = () => <Basic {...{ title: 'hello world' }} />;
export default { title: 'Basic' };
This is my storybook main.js
main.js
module.exports = {
stories: ['../**/*.stories.tsx', '../**/**/*.stories.tsx'],
addons: [
'#storybook/addon-actions',
'#storybook/addon-links',
]
};
Appreciate any suggestions. Thanks
It turns out the one thing I didn't include in my configs above was my jest.config.js file.
It turns out the following was causing this problem:
jest.config.js ! broken
moduleNameMapper: {
'src/(.*)': '<rootDir>/src/$1',
...
},
Today I decided to strip everything down, and in the process came across ts-jest config examples where the regex had an exact path, ie started with ^ and ended with $, ie not a wild match.
https://kulshekhar.github.io/ts-jest/user/config/
Not that I thought much of it or why it would break storyshots only and nothing else but anything around file matching and resolutions I thought was worth ensuring accuracy. I updated my regex to match the paths above and BINGO - NO MORE ERROR !!! HAHAH. A nice stroke of luck.
jest.config.js £ fixed
moduleNameMapper: {
'^src/(.*)$': '<rootDir>/src/$1'
...
},

eslint + jsconfig + nextjs module path aliases (absolue path import - #)

I am trying to import the files using custom aliases following the nextjs documentation.
My current approach is
from
import Header from '../../../components/Header';
to
import Header from '#components/Header';
I am getting the expected result. But eslint throws the following error:
unable to resolve path to module (eslint - import/no unresolved)
And I have tried adding the following line in my eslintrc file to resolve the error
settings: {
'import/resolver': {
node: {
paths: ['src'],
},
},
},
But still the eslint throws the same error.
What is the correct approach to resolve this one?
Thanks in advance...
Note: I don't want to remove eslint and I need #components import aliases
Finally after digging into lots of GitHub answers and etc...
Inside your eslintrc file... add the following aliases
settings: {
'import/resolver': {
alias: {
map: [
['#components', '../../../components/'],
['#images', '../../../assets/images/'],
],
extensions: ['.js', '.jsx'],
},
},
},
and also to fix flow error
inside your flowconfig file add the name_mapper
module.name_mapper='^#components' ->'<PROJECT_ROOT>/../../../components'
module.name_mapper='^#images' ->'<PROJECT_ROOT>/../../../assets/images'
You need to also install npm i -D eslint-import-resolver-typescript and then add below to eslint config file:
"settings": {
"import/resolver": {
"typescript": {} // this loads <rootdir>/tsconfig.json to eslint
},
}
Reference: https://gourav.io/blog/nextjs-cheatsheet
You can try adding your custom paths in tsconfig.json/jsconfig.json, like so:
Add a baseUrl in your compilerOptions (in my case it's "baseUrl": ".")
Add your paths in a paths object:
"paths": {
"components": ["components/*"],
}

How to avoid using relative path imports (/../../../redux/action/action1) in create-react-app

I've been using create-react-app package for creating a react website. I was using relative paths throughout my app for importing components, resources, redux etc. eg, import action from '../../../redux/action
I have tried using module-alis npm package but with no success. Is there any plugin that I can use to import based on the folder name or alias i.e. an absolute path?
Eg., import action from '#redux/action' or import action from '#resource/css/style.css'
Create a file called .env in the project root and write there:
NODE_PATH=src
Then restart the development server. You should be able to import anything inside src without relative paths.
Note I would not recommend calling your folder src/redux because now it is confusing whether redux import refers to your app or the library. Instead you can call your folder src/app and import things from app/....
We intentionally don't support custom syntax like #redux because it's not compatible with Node resolution algorithm.
The approach in the accepted answer has now been superseded. Create React App now has a different way to set absolute paths as documented here.
To summarise, you can configure your application to support importing modules using absolute paths by doing the following:
Create/Edit your jsconfig.json/tsconfig.json in the root of your project with the following:
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}
Once you have done this you can then import by specifying subdirectories of "src" (in the following example, components is a subdirectory of src) e.g.
import Button from 'components/Button'
We can use webpack 2 resolve property in the webpack config.
Sample webpack config using resolve :
Here component and utils are independent folder containing React components.
resolve: {
modules: ['src/scripts', 'node_modules'],
extensions: ['.jsx', '.js'],
unsafeCache: true,
alias: {
components: path.resolve(__dirname, 'src', 'scripts', 'components'),
utils: path.resolve(__dirname, 'src', 'scripts', 'utils'),
}
}
After that we can import directly in files :
import UiUtils from 'utils/UiUtils';
import TabContent from 'components/TabContent';
Webpack 2 Resolve Reference
After you try Ben Smith's solution above if you find eslint complains about importing absolute path add the following line to your eslint config:
settings: {
'import/resolver': {
node: {
paths: ['src'],
},
},
},
replace 'src' with your folder if you use your own boilerplate with your folder's name.
Feb 2010
Wasted about an hour on this.
An example is below:
Goal: Import App.css in HomePage.js
myapp\src\App.css
myapp\src\pages\HomePage.js
File: jsconfig.json
{
"compilerOptions": {
"baseUrl": "src"
}
}
File: src\pages\HomePage.js
import "App.css";
The alias solution for craco or rewired create-react-app is react-app-alias for systems as: craco, react-app-rewired, customize-cra
According docs of mentioned systems replace react-scripts in package.json and configure next:
react-app-rewired
// config-overrides.js
const {aliasWebpack, aliasJest} = require('react-app-alias')
const options = {} // default is empty for most cases
module.exports = aliasWebpack(options)
module.exports.jest = aliasJest(options)
craco
// craco.config.js
const {CracoAliasPlugin} = require('react-app-alias')
module.exports = {
plugins: [
{
plugin: CracoAliasPlugin,
options: {}
}
]
}
all
Configure aliases in json like this:
// tsconfig.paths.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"example/*": ["example/src/*"],
"#library/*": ["library/src/*"]
}
}
}
And add this file in extends section of main typescript config file:
// tsconfig.json
{
"extends": "./tsconfig.paths.json",
// ...
}
I am using babel-plugin-module-resolver for my project to resolve that problem.
babel-plugin-module-resolver also is the same as module-alis. So I think you should just resolve using module-alis problem.
Because you didn't tell us why using module-alis was fail? So i cant show you how to fix it.
Dont give up your solution while you dont know the reason!
in package.json file,
eject this code in the scripts object like this..
"scripts": {
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js --env=jsdom",
"eject": "NODE_PATH=src/ react-scripts eject"
},
this will enable the absolute path imports in your app
None of the answers worked for me. Some didn't work at all and others worked but the import was already inside src, for example:
import something from 'path/to/file'.
Whereas I wanted to be able to do:
import something from 'src/path/to/file'
Here is how I solved it:
tsconfig.json
{
"compilerOptions": {
// ...
"baseUrl": ".",
"rootDirs": [
"src"
]
},
"include": [
"src"
]
}

How to use TypeScript on an AngularJS application (1.x) with Webpack

I'm following the official tutorial to migrate from AngularJS (1.x) to Angular (2+).
I managed to break my application into Components and use ES6 with a module loader, in my case Webpack, but now I'm not sure how to setup TypeScript.
I guess I need to install the TypeScript compiler and somehow tell Webpack to use it. How can I do it?
The source code is available here: https://github.com/shindarth/othello
First of all run:
npm install typescript awesome-typescript-loader source-map-loader --save-dev
this will install typescript, awesome-typescript-loader and source-map-loader to the list of the devDependencies of package.json file.
Then create the typescript compiler config file named tsconfig.json with a basic configuration inside:
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": true
}
}
you can further customise the ts compiler options referring to the official tsconfig.json documentation.
At this point we can rename all our *.js files to .ts.
Note that wherever we were importing angularjs using:
import angular from 'angular';
we need to change it with:
import * as angular from 'angular';
Finally we can tell WebPack to use the ts compiler to compile our *.ts source files.
So edit the file webpack.config.js as follows:
1) Edit the entry file name (since we renamed it and changed its extension to .ts).
In my case it was ./app/index.js before, change to:
entry: {
app: './app/index.ts'
},
2) then below add the following:
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".ts", ".tsx", ".js", ".json"]
},
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" },
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
]
},

Persuading webpack to use node_modules/#types

I'm trying to get to grips with using Typescript 2, Webpack and Angular 1.5, but when building Webpack keeps complaining that it:
Cannot resolve module '#types/angular' in C:\play\gt\src
I'm stumped. Been Googling this and messing about but am getting nowhere.
My app.ts looks like:
import * as angular from "#types/angular";
let app = angular.module ("GT.module", []);
My tsconfig looks like:
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"sourceMap": true,
"typeRoots" : [
"node_modules/#types"
]
},
"exclude": [
"node_modules",
"**/*.spec.ts"
],
"include" : [
"src/**/*"
]
}
...and lastly webpack config:
module.exports = {
entry: './src/app.ts',
output: {
filename: './dist/app.js'
},
devtool: "source-map",
resolve: {
extensions: ['', '.webpack.js', '.web.js', '.ts', '.js'],
modulesDirectories: ["node_modules"]
},
module: {
loaders: [
{ test: /\.ts$/, loader: 'ts-loader' }
]
}
}
What is your directory tree looks like?
It should look like this:
node_modules/
#types/
angular/
src/
tsconfig.json
webpack.config.js
Then you don't need "typeRoots" : ["node_modules/#types"]
and import * as angular from "#types/angular"; should became import * as angular from "angular";
The Typescript compiler 2.0 will know where to look to find the typings at the right places (ie: in node_modules/#types)
#types are not modules you can import, they are typedefs for the compiler to reference.
The #types/angular package does not actually implement .module and your code will break (if it ever compiles).
You probably want to do something more like:
/// <reference path="../node_modules/#types/angular/index.d.ts" />
import * as angular from "angular";
let app = angular.module ("GT.module", []);
But, you typically won't even need the reference, as the compiler will automatically include typedefs from #types/* packages unless you tell it not to (by setting types or typeRoot in your tsconfig.json). This behavior was added in v2 and is fairly recent.

Resources