Given the following tsconfig.json
import { Potato } from "#src/potato";
import { garbage } from "#rules/garbage";
import { Foo } from "external-module";
require("#src/potato");
jest.mock("#rules/garbage");Given a file in ./src
import { Potato } from "./potato"; // relative paths are not okay
import { garbage } from "#src/rules/garbage"; // import can be shortened
require("./potato");
jest.mock("#src/rules/garbage");To add new functions which takes a single string parameter,
you can define your own functions that are considered import functions.
For example, defining the following in .eslintrc will check the first
parameter of a function named potato for aliasing.
{
// ...
"rules": {
// ...
"@limegrass/import-alias/import-alias": [
"error",
{
"aliasImportFunctions": ["require", "mock", "potato"],
},
],
},
}This was based off an assumption that custom mock functions will take a similar
parameter to require or jest.mock, but please submit an issue detailing
your usage if this does not serve your needs.
The relative path to tsconfig.json can be explicitly specified using the aliasConfigPath
configuration key. An example for a tsconfig found in a config folder of a project could be
{
// ...
"rules": {
// ...
"@limegrass/import-alias/import-alias": [
"error",
{
"aliasConfigPath": "config/tsconfig.json",
},
],
},
}One potentially useful case of this is where you have nested tsconfig.json files.
You can the aliasConfigPath option with the __dirname variable in JavaScript ESLint config files
to configure some dynamic roots against different project roots.
See this issue for an example usage.
It is possible to allow relative imports for some paths if desires through configuring
a relativeImportOverrides configuration parameter on the rule. Each configuration requires
a path and a depth to be specified, where a depth of 0 allows imports of sibling modules,
a depth of 1 allows imports from siblings of the parent module, and so on.
The follow example would allow sibling imports for the entire project.
{
// ...
"rules": {
// ...
"@limegrass/import-alias/import-alias": [
"error",
{
"relativeImportOverrides": [{ "path": ".", "depth": 0 }],
},
],
},
}With a configuration like { path: "src/foo", depth: 0 }
- Relative paths can be used in
./src/foo. - Relative paths can be used in
./src/foo/bar. - Relative paths can NOT be used in
./src.
With a configuration like { path: "src", depth: 0 }
- Relative paths can be used in
./src/foo. - Relative paths can be used in
./src/bar/baz. - Relative paths can be used in
./src.
In ./src/foo with path: "src"
import "./bar"for./src/barwhendepth>=0.import "./bar/baz"whendepth>=0.import "../bar"whendepth>=1.
Regular expression patterns serve as a potential alternative to path overrides.
With a configuration like { pattern: "index.ts", depth: 0 }
- Relative paths can be used in files such as
./src/index.ts. - Relative paths can be used any file in the folder
./src/index.ts/*. - Relative paths can NOT be used in files such as
./src/foo.ts.
With a configuration like { pattern: "index\\.(ts|js)$" depth: 0 }
- Relative paths can be used in any file that ends with
index.jsorindex.ts. - Relative paths can be NOT in the folder
./src/index.ts/*. - Relative paths can be NOT used in
./src/foo.ts.
If a file matches by both patterns and paths, the maximum depth allowed is simply the largest of all matched overrides.
The relativeImportOverrides option only permits relative
imports to be used for the configured overrides.
Use the isRelativeImportOverridesEnforced option to require
matches import using relative paths when possible.
As an example, the configuration below will require relative imports
for any sibling or their nested descendent from within src/components
{
// ...
"rules": {
// ...
"@limegrass/import-alias/import-alias": [
"error",
{
"isRelativeImportOverridesEnforced": true,
"relativeImportOverrides": [
{ "path": "src/components", "depth": 0 },
],
},
],
},
}// ./src/components/code.ts
import { Potato } from "#src/potato"; // valid
import { garbage } from "#src/components/garbage"; // invalid! - prefers ./garbageBy default, TypeScript can resolve your modules based off absolute paths from
the baseUrl defined in tsconfig.json. This means that if your TSConfig looks like
{
// ...
"compilerOptions": {
// ...
"baseUrl": ".",
"paths": {
"#src/*": ["src/*"],
},
},
}then when trying to import a file src/potato.ts
import { Potato } from "src/potato"; // valid as it is resolved through TypeScript's baseUrl as `./src/potato`
import { Potato } from "#src/potato"; // also valid as it uses a defined path to resolve itYou can choose whether or not these types of absolute paths which do not use an
alias are acceptable in your project by configuring the isAllowBaseUrlResolvedImport
plug-in option for this rule.
{
// ...
"rules": {
// ...
"@limegrass/import-alias/import-alias": [
"error",
{
"isAllowBaseUrlResolvedImport": false,
},
],
},
}This value is false by default in the recommended config to encourage being as explicit
as possible with path definitions. When this value is set to false,
the path defined through the baseUrl is not considered valid.
import { Potato } from "src/potato"; // now invalid
import { Potato } from "#src/potato"; // valid as expectedWhile another suggestion could be to assign no paths and use only the baseUrl-resolved paths;
this does not currently function when this is the case. If this is your preference and this is
not yet implemented, feel free to file a new issue.
{ // ... "compilerOptions": { // ... "paths": { "#src/*": ["src/*"], "#rules/*": ["src/rules/*"], }, }, }