Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Absolute module path resolution in TypeScript files in Visual Studio Code

I can't seem to convince Visual Studio Code to resolve absolute TypeScript module paths. Relative paths work, but absolute don't. I would like Visual Studio Code to resolve module paths from ./src folder on.

// This works when source file is in /src/here/there/file.ts
// and importing an interface in /src/api/interfaces.ts
import { Interface } from '../../api/interfaces';

// This doesn't work
import { Interface } from 'api/interfaces';
import { Interface } from '/api/interfaces';
import { Interface } from 'src/api/interfaces';
import { Interface } from '/src/api/interfaces';

// This works, but it is of course not supposed to be used
import { Interface } from 'c:/..../src/api/interfaces';

The last one of course doesn't count as each developer's project path is highly likely different. But even if we'd all set a system variable %ProjectXRoot% we can't use this variable in the code. Visual Studio Code will not resolve such module path. I've tried.

// Won't work
import { Interface } from '%ProjectXRoot%/api/interfaces';

Currently installed versions
• TypeScript: 1.8.10
• VSCode: 1.1.1

Question

I've tried to somehow configure Visual Studio Code to resolve absolute module paths, but I can't seem to do so. I've tried configuring tsconfig.json (in the project root) by adding baseUrl in two different places.

{
    ...
    "compilerOptions": {
        "baseUrl": "./src", // Doesn't work
        ...
    },
    "baseUrl": "./src", // Doesn't work either
    ...
}

I've tried values like src, ./src and ./src/, but none of them work in any of the upper configuration places.

So how does one configure Visual Studio Code to resolve absolute module paths from a certain folder?

If that's not possible, it would be at least better to resolve absolute paths from project root. How does Visual Studio Code determine that? Is it where you Open Folder or is it where the .vscode folder is?

But it would still be a viable solution for absolute paths. I've tried using ~ similar to Visual Studio, but to no avail either.

(Unresolved)

-- As steinso points out in his answer, all modules starting with /, ./ or ../ are considered relative. Especially the first one surprised me completely as I usually consider that a project root-relative path.

But this fact basically means that the main question now becomes: How can I provide module imports as absolute paths (from some project root folder path) at all? Starting paths with slashes usually meant absolute, but in this case it doesn't.

Even when I set compiler option moduleResolution to classic (so module resolution wont be looking into node_modules folder) the second set of imports above should actually all work as per Microsoft's linked document. But for some reason I still get red squiggly lines in Visual Studio Code and errors during compilation.

So how can I import a specific project module without providing an exact relative path to it, but rather just its own project-relative path?

like image 815
Robert Koritnik Avatar asked Jun 03 '16 05:06

Robert Koritnik


People also ask

How do you use absolute path in TypeScript?

To be able to use absolute paths in TypeScript we can set the baseUrl property in the tsconfig. json file. With this, we define src as our root directory (for module resolution).

What is module resolution in TypeScript?

Module resolution is the process the compiler uses to figure out what an import refers to. Consider an import statement like import { a } from "moduleA" ; in order to check any use of a , the compiler needs to know exactly what it represents, and will need to check its definition moduleA .

What is a jsconfig file?

The jsconfig. json file specifies the root files and the options for the features provided by the JavaScript language service.

How do I get the relative path of a file in Visual Studio code?

Press Ctrl+Shift+H (Mac: Cmd+Shift+H ) and start typing the file you want. 🪄 Select your file from the dropdown!


3 Answers

To be able to use absolute paths from import in TypeScript using Visual Studio Code you should be using next version of TypeScript - typescript@next which is TypeScript v2. For that do the following:

  1. Install typescript@next via npm. For installing TypeScript v2.x

    npm i typescript@next -D

  2. In Visual Studio Code

    i) Go to menu File → Preferences → Workspace Settings (This generates the .vscode directory at the project root and initializes the settings.json file.)

    ii) Put the following key:value pair in settings.json file

    "typescript.tsdk": "node_modules/typescript/lib"

  3. In tsconfig.json add following key:value pair to 'compilerOptions'

{
  "compilerOptions" : {
    "baseUrl": "./",
    "paths" : {
      "src/*": ["./src/*"]
    }
  }
}
  1. Reload Visual Studio Code

If you have the following directory structure:

+ node_modules
+ src
| + app
| |  + shared
| |  |  -service.ts
| |  -main.ts
+ typings
- tsconfig.json
- webpack.config.json
- package.json
- index.html

Then to import /src/app/shared/service.ts from main.ts you could now import {} from 'src/app/shared/service;

If you are using webpack and ts-loader for transpiling the .ts files, you should add following to the resolve section of webpack.config.js configuration file.

resolve: {
    extensions: ['', '.js', '.ts'],
    alias: {
      "src": path.resolve('./src')
    }
  }

Please refer to this for absolute module resolution.

like image 153
Lekhnath Avatar answered Oct 04 '22 20:10

Lekhnath


You need to specify:

    "compilerOptions": {
        "moduleResolution": "classic"
        ...

The base path will then default to the directory of your tsconfig.json, add rootDir in compilerOptions to change it. EDIT: This does not seem to have any effect.

This will allow imports such as:

import { Interface } from 'api/interfaces';

Note that any path starting with . or ../ or / is considered relative.

Edit: Module resolution

Be aware of how the modules are resolved. The module path is still some what relative to the current file.

Let's use an example to illustrate for the current scenario:

Let's say you import { Interface } from "api/interfaces", from source file /src/views/View.ts. Typescript would then look for the module in the following paths:

  1. /src/views/api/interfaces.ts
  2. /src/api/interfaces.ts
  3. /api/interfaces.ts

Note: how this still makes it relative, imagine if you import {Home} from "Home/Home" when you are located in /src/views/View.ts. In this case it would work even if the path is /src/views/Home/Home.

These are the possible resolutions:

  1. /src/views/Home/Home -> Note how this would work.
  2. /src/Home/Home
  3. /Home/Home

More information can be found here: http://www.typescriptlang.org/docs/handbook/module-resolution.html

like image 38
steinso Avatar answered Oct 04 '22 20:10

steinso


If you've set up paths correctly:

{
  …
  "compilerOptions": {
    …
    "baseUrl": ".",
    "paths": {
      "~/*": ["app/assets/javascript/*"],
      "*": ["node_modules/*", "app/assets/javascript/packs/*"]
    }
  }
}

And if you're still having issues, maybe try reloading Visual Studio Code: Cmd/Ctrl + Shift + P and type reload window.

It just randomly stopped working for me and is reporting problems. I spent around 20 minutes online trying to figure out what changed, only to realize that Visual Studio Code can glitch on absolute path resolution.

like image 27
RWDJ Avatar answered Oct 03 '22 20:10

RWDJ