Import module from root path in TypeScript

52,388

Solution 1

(Re-posting my answer to avoid puppy-socket.)

Using the compilerOptions.baseUrl property I was able to do the below import. This allowed me to have a complete root-to-expected-path, which helps my code maintainance, and works in any file, independently of the current folder. The below examples will have the src folder of my project as the modules root.

Important advice: this baseUrl property doesn't affect the entry webpack file (at least for me?), so separate a main file inside the src folder with this example, and run it from the entry (i.e., import { Main } from './src/Main'; new Main;), only once.

// browser: directory inside src;
//   * net: A TS file.
import { URLRequest } from 'browser/net';

tsconfig.json example:

{
    "compilerOptions": {
        "baseUrl": "./src",
        "module": "commonjs",
        "noImplicitReturns": true,
        "noImplicitThis": true,
        "noUnusedLocals": true,
        "preserveConstEnums": true,
        "removeComments": true,
        "sourceMap": true,
        "strictNullChecks": true,
        "target": "ES6"
    },

    "include": [
        "./src/**/*.ts",
        "./src/**/*.d.ts"
    ]
}

However, it won't directly work with webpack. The same thing must be done at the webpack options. This is how it worked in webpack 2:

module.exports = {
  ...
  , resolve: {
      ...
      , modules: [ path.join(__dirname, './src') ]
    }
}

Solution 2

I needed to set both baseUrl and rootDir to point to my src folder in tsconfig.json

{
  "compilerOptions": {
    "baseUrl": "./src",
    "rootDir": "./src",
  ...
}

I could then import .tsx files without needing a prefixed '/' or a relative path.

e.g. import BreadCrumb from 'components/BreadCrumb'

Solution 3

TypeScript imports use / at the start of a path to denote the root directory. To import a file relative to your current file either leave off the initial slash or use ./.

// Current script: C:\product\src\com\name\product\blah.ts
import { thing } from './com/name/product/thing';

By default the TypeScript compiler assumes the root of the project is the same as the location of your tsconfig.json.

You can specify a new root by specifying the rootDir property of the compilerOptions property in the tsconfig.

For a list of all available property settings consult the tsconfig definition found here.

Solution 4

Just for record

If you want use absolute import from your project, Do not use / as prefix, such as /src/config/cfg, just use as src/config/cfg

As https://stackoverflow.com/a/46229294/7529562 pointed, / stand for System root,

tsc will complain cannot find module

Share:
52,388

Related videos on Youtube

Klaider
Author by

Klaider

Updated on February 28, 2021

Comments

  • Klaider
    Klaider over 3 years

    Let's suppose I've a project, and its main source directory is:

    C:\product\src
    

    Based on this directory, every import path would be relative to it. I.e., suppose:

    // Current script: C:\product\src\com\name\product\blah.ts
    
    import { thing } from '/com/name/product/thing';
    

    same as:

    // Current script: C:\product\src\com\name\product\blah.ts
    
    import { thing } from '../../../com/name/product/thing';
    

    My entry compilation file would be at:

    C:\product\src
    

    for instance. So, is there a way to specify this such entry path (C:\product\src, for example) at the compiler options? I need to specify this in the tsconfig.json file, because I'll use webpack.

    I've tried my above example, but TypeScript says the requested module cannot be found:

    // Current script: A.ts
    
    import { B } from '/com/B';
    
    
    // Current script: B.ts
    
    export const B = 0;
    

    My tsconfig.json file (inside another project, but both similiar):

    {
        "compilerOptions": {
            "module": "commonjs",
            "noImplicitReturns": true,
            "noImplicitThis": true,
            "noUnusedLocals": true,
            "preserveConstEnums": true,
            "removeComments": true,
            "sourceMap": true,
            "strictNullChecks": true,
            "target": "ES6"
        },
    
        "include": [
            "./src/**/*.ts",
            "./src/**/*.d.ts"
        ]
    }
    
    • Tomáš Hübelbauer
      Tomáš Hübelbauer over 7 years
      C:\product\src + ../../../com/name/product/thing is not C:\product\src\com\name\product\blah.ts. Am I missing something? You want disallow ..ing up a certain root directory?
    • Admin
      Admin over 7 years
      @TomášHübelbauer The // C:\product\src\com\name\product\blah.ts comment means that the following script with import declaration is the blah.ts file, it's not related to the import path. Sry! Not sure what you meant by .., I'm not very good at English :/.
    • Teddy Sterne
      Teddy Sterne over 7 years
      Please post your tsconfig.json
    • Klaider
      Klaider over 7 years
      @TeddySterne Added.
  • Klaider
    Klaider over 7 years
    Thanks for the assumption of the root directory, however I can't still import a file relative to its root, as TypeScript continues saying that the import module doesn't exist/can't be found. I've tried with and without slash, but nothing, same with ./.
  • Teddy Sterne
    Teddy Sterne over 7 years
    Try switching module to node
  • Klaider
    Klaider over 7 years
    Thanks for the elaboration, however that's not broadly exactly what I was looking for. I know I can use the .. and ./ tokens for relative-importing, there's yet an example in my question.
  • Aravind
    Aravind over 7 years
    what is that you were looking for
  • Klaider
    Klaider over 7 years
    I'm trying to avoid deep-relative paths, I want to specify a relative path from the project root, not by the current file root. For example, my root would now be the src folder. Suppose I've a file src/blah/Class.ts, in which import { Export } from 'export' would refer to src/Export.ts. I don't want to depend on .. or ./ tokens, unfortunately they made me almost create a new programming language to replace TypeScript, they made my code maintainance ugly.
  • Aravind
    Aravind over 7 years
  • Eyal Perry
    Eyal Perry about 7 years
    Awesome, answer but don't forget to also put node_modules in there.
  • Greg
    Greg almost 7 years
    I found the includes section unnecessary and will even attempt to compile what's in node_modules. I set baseUrl, rootDir, ouputDir in tsconfig. In webpack I added node_modules as @EyalPerry pointed out. Seems to be working great.
  • raphinesse
    raphinesse almost 7 years
    / always refers to the file system root. More details
  • Matthew Dean
    Matthew Dean about 5 years
    This isn't true. Support was added in 2017 -> github.com/Microsoft/TypeScript/issues/19318
  • porges
    porges almost 5 years
    I'm using create-react-app and setting only baseUrl was sufficient. Thanks! 👍
  • Mr5o1
    Mr5o1 over 4 years
    This works in vscode linting, and tsc will build it fine, but then I get module not found when I try to run the compiled code.
  • electrovir
    electrovir about 4 years
    To get a path like src/config/cfg to work for me I had to provide a baseUrl in my tsconfig.json.
  • electrovir
    electrovir about 4 years
    For me I only had to provide a baseUrl.
  • joematune
    joematune over 2 years
    Don't forget to restart your development server for this to work 👍