Fixing absolute imports in TypeScript

TypeScript has a cute feature with a small problem causing a huge impact.

Cute Feature: absolute imports with baseUrl

{
"compilerOptions": {
"baseUrl": "src"
}
}

Now you can import all files relative to baseUrl, instead of to the file you’re in! In larger projects this saves you a lot of annoyance — you can write instead, anywhere in your project.

Unfortunately, these imports won’t work in Javascript any more. And the TypeScript team are opposed to the compiler converting these import paths to relative when it does compile to Javascript, since:

Module names are considered resource identifiers and are not changed by the compiler.

So now your module can’t be imported into other modules

Most build toolchains will have some support but with tradeoffs. So, there are some… workarounds

  • Compile your TypeScript with instead. Drawback: No definition files, and no type safety at compile time.
  • In a TypeScript parent project, set up your parent (importing) project to resolve imports relative to using , or manually “absolute to project-root relative” mappings in your parent’s . Very manual.
  • Build your library with , which produces a single file with no imports, but no typing definition files.
  • Build using webpack and , with the right plugin configuration.
  • And others hacks involving symlinks or post-build scripts

Best solution: Use the compiler itself to compile these imports to Javascript

The TypeScript compiler supports an API much like Babel’s, which allows us to transform the code it outputs. Transformers can basically turn any code into any other valid code, so we use it to re-write easy-to-write but hard-to-compile absolute imports into relative imports that and Javascript expect. makes it easy to compile or run with transformer plugins!

✨✨✨

✨✨✨

It’s as easy as adding the plugin to your and running or as you’d usually run their native typescript equivalents.

We’ve been using it at ActivePipe (my excellent workplace) in production and are enjoying the advantage of absolute import paths when refactoring and breaking apart our larger modules while still maintaining flexibility of compiling to basically any project.

Contributions and bug reports welcome and hopefully this eases some pain the TypeScript community has been having writing modular and packaged code.

i make cool shit on the internet

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store