Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript Import Path Alias

I am currently working on a TypeScript application which is comprised of multiple Node modules written in TypeScript, that are installed into the node_modules directory.

Before continuing, I would like to note that I am using TypeScript 2.0, I am not adverse to using the 2.1 dev release if need be as well. I just want to get this working.

The structure of each Node module is something along the lines of:

dist/     es2015/         index.js         utils/             Calculator.js             Calculator.d.ts             Date.js             Date.d.ts             Flatpack.js             Flatpack.d.ts src/     index.ts     utils/         Calculator.ts         Date.ts         Flatpack.ts 

The dist folder is the generated source, with this path being configured using outDir inside of my tsconfig.json file. I have also configured the main property in my package.json to be dist/es2015/index.js.

Important things to note:

  • In my project I am using moduleResolution type of node
  • I am using TypeScript 2.0
  • I am not asking how to import a file from within the package. I am installing the package via Npm and then importing it via packagename/ from within an application that is using this module.

Now comes my question/issue. Whilst importing files from this module, I would like to be able to do this:

import {Sin, Cos, Tan} from "common-utils/utils/Calculator"; 

However, the file cannot resolve to the dist/es2015/utils directory. Ideally I would like my imports to resolve from this specific dist folder and not from the root, which is what appears to be happening.

The above import needs to be written as the following to get it to work:

import {Sin, Cos, Tan} from "common-utils/dist/es2015/utils/Calculator"; 

However, writing dist/es2015 each time is not ideal and it just makes some of the imports look really long. Is there a way I can configure my module to resolve to the dist/es2015 directory? I don't want to have to put in overrides inside of my project, ideally each module would specify where files are resolved from.

If you are still unsure what I am asking (and I apologise if this is confusing) in Jspm when you create a plugin/module to be used with Jspm, you can specify inside of the package.json for the module something like the following:

  "jspm": {     "registry": "npm",     "jspmPackage": true,     "main": "my-module",     "format": "amd",     "directories": {       "dist": "dist/amd"     }, 

I am looking for the equivalent of the above in TypeScript (if it exists). A mapping directive, so when the end user runs npm install my-cool-package and then in their app tries to import something, all imports by default resolve to the commonjs directory (the above example for Jspm uses amd, but same premise).

Is this possible or am I misunderstanding something here? I know some new path mapping features were added into the latest release, but documentation on using them is almost nonexistent.

like image 240
Dwayne Charrington Avatar asked Jul 26 '16 23:07

Dwayne Charrington


People also ask

How do I add an alias in Tsconfig?

Go to tsconfig. json file and add baseUrl and paths variables which specify Typescript transpiler to resolve modules. baseUrl: Source code directory which specified where to find modules for import statements. Step 2: Configure NodeJS runtime to handle path aliases.

What are path aliases?

🎉 Path aliasing or aliases are preconfigured names used to replace long paths in files and resolve to certain directories on a codebase.


2 Answers

So after reading your comment, I realized I misunderstood your question! If you want to control the paths from an imported package's perspective, just use set the main property of your package.json to a file that properly represents the object graph of your module.

{   "main": "common-utils/dist/es2015/index.js" } 

If you're attempting to control the import paths from a project's perspective, what you're looking for is TypeScript 2's new path mapping feature for module resolution. You can enable path mapping by configuring your tsconfig.json as follows:

{   "compilerOptions": {     "baseUrl": ".",     "paths": {       "angular2/*": ["../path/to/angular2/*"],       "local/*": ["../path/to/local/modules/*"]     }   } } 

Then, in your TypeScript files, you can import the modules like this:

import { bootstrap } from 'angular2/bootstrap'; import { module } from 'local/module'; 

For more details about the Path Mapping feature in TypeScript 2 see this Github issue.

In your case, I think the following configuration should work:

{   "compilerOptions": {     "baseUrl": ".",     "paths": {       "common-utils/utils/*": ["./node_modules/common-utils/dist/es2015/utils/*"]     }   } } 
like image 97
fny Avatar answered Oct 02 '22 21:10

fny


If you are using paths, you will need to change back absolute paths to relative paths for it to work after compiling typescript into plain javascript using tsc.

Most popular solution for this has been tsconfig-paths so far.

I've tried it, but it did not work for me for my complicated setup. Also, it resolves paths in run-time, meaning overhead in terms of your package size and resolve performance.

So, I wrote a solution myself, tscpaths.

I'd say it's better overall because it replaces paths at compile-time. It means there is no runtime dependency or any performance overhead. It's pretty simple to use. You just need to add a line to your build scripts in package.json.

The project is pretty young, so there could be some issues if your setup is very complicated. It works flawlessly for my setup, though my setup is fairly complex.

like image 23
Joon Avatar answered Oct 02 '22 21:10

Joon