How to get tsc to Resolve Absolute Paths when Importing Modules using baseUrl?

Zsw picture Zsw · Feb 21, 2017 · Viewed 7.8k times · Source

Consider a simple typescript project with the following directory structure:

|   package.json
|   tsconfig.json
|               
\---src
    |   app.ts
    |   
    \---foobar
            Foo.ts
            Bar.ts

tsconfig.json has been configured to have ./src/ be the baseUrl.

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es6",
        "noImplicitAny": true,
        "removeComments": true,
        "preserveConstEnums": true,
        "outDir": "./dist/",
        "baseUrl": "./src/"
    },
    "include": [
        "./src/**/*"
    ],
    "exclude": [
        "node_modules"
    ]
}

Now suppose we want to import Foo in Bar.ts. My understanding is that by setting the baseUrl, we can now use absolute paths to import modules

import { Foo } from 'foobar/Foo'

as opposed to relative paths

import { Foo } from './Foo'

If my understanding is correct, the typescript compiler should be able to automatically resolve foobar/Foo to ./Foo when compiling Bar.ts.

import { Foo } from 'foobar/Foo';

export class Bar {
  foo: Foo;

  constructor(num: number) {
    this.foo = new Foo(num);
  }
}

Running tsc compiles without errors. Yet, when we actually look at the compiled Bar.js, we would see that the path has not been resolved correctly, which would give us a Cannot find module error if we were to run it.

"use strict";
const Foo_1 = require("foobar/Foo");
class Bar {
    constructor(num) {
        this.foo = new Foo_1.Foo(num);
    }
}
exports.Bar = Bar;

So my question is: How can I get tsc to correctly resolve the absolute paths when importing modules using baseUrl? Or if this is not something that can be done, what is the purpose of baseUrl then?

Answer

Seamus picture Seamus · Feb 21, 2017

The problem is that your module loader does not know how to find the module given the absolute path foobar/Foo.

The TypeScript compiler (tsc) is resolving the module paths correctly, otherwise you would get compilation errors. But it is trusting you to configure your module loader appropriately.

For example, from the documentation for RequireJS:

Supported configuration options:

baseUrl: the root path to use for all module lookups.

The TypeScript documentation talks a little about why you might need baseUrl:

Using a baseUrl is a common practice in applications using AMD module loaders where modules are “deployed” to a single folder at run-time. The sources of these modules can live in different directories, but a build script will put them all together.