$ npm i -D @nodejs-loaders/alias
$ node --import @nodejs-loaders/alias main.js
See README.md
in the repository's root for more details.
Environments: dev, test
Compatible APIs: module.register
, module.registerHooks
This loader facilitates TypeScript's paths
, handling the (important) half of work TypeScript ignores. It looks for a tsconfig.json
in the project root (the current working directory) and builds aliases from compilerOptions.paths
if it exists. If your tsconfig lives in a different location, see Configuration below.
[!CAUTION] Consider using Node.js's subpath imports. It's more performant and doesn't require a loader. If you are using
tsc
for type-checking, set compilerOptions.moduleResolution tonode16
or higher.
In order for Alias loader to leverage baseUrl
, there must be at least 1 path in compilerOptions.paths
. If, for example, you wish to only facilitate absolute specifiers (relative to some base folder, like ./src
, such as is common in Next.js projects), include the following "dummy" "paths"
:
{
"compilerOptions": {
"baseUrl": "./src",
"paths": { "*": ["./*"] }, // ⚠️ Effectively prepends ./src
},
}
[!IMPORTANT] If an aliased specifier successfully resolves to a "local" module, you will not be able to reach one in
node_modules
. This behaviour is consistent with Node.js and tsc, but it can still be a gotcha.
This is commonly used to reference the project root; common prefixes are @/
(or some variation like @app/
) and …/
: import foo from '…/app/foo.mts;
→ ${project_root}/src/app/foo.mts
.
[!TIP] Due to package namespacing (aka "scopes") it may be best to avoid using the "at" symbol (
@
) since that could lead to confusion over what is a package and what is an alias (especially if you eventually add a package named with the alias you're using). You should similarly avoid the octothorpe/hash symbol (#
) because that is used by Node.js's sub-path imports.
[!NOTE] When configuring these aliases, ensure astrisks (
*
) are used correctly; configuring this for TypeScript can be extremely confusing. See Why are these tsconfig paths not working? for some of the litany of ways configuration can fail.
This is a static specifier similar to a bare module specifier: foo
→ ${project_root}/src/app/foo.mts
. This may be useful when you have a commonly referenced file like config (which may conditionally not even live on the same filesystem): import CONF from 'conf';
→ ${project_root}/config.json
.
The are 2 ways to configure the tsconfig alias loader uses:
- Environment variable:
TS_NODE_PROJECT
-
node:module.register
's options.data argument:register(…, …, { data: import.meta.resolve(…) })
.
For both options, the value can be either a simple filename like 'tsconfig.whatever.json'
or a fully resolved location 'file:///path/to/someplace/tsconfig.whatever.json'
(or its absolute file path).