19

I want to create local modules in my TypeScript (with Angular 2) app and then simple reference to any file with importing module like myApp/components, myApp/pipes etc., not using relative path (../../../MyComponent) as I have to do now.

For instance, Angular 2 can be used like this. (And I haven't found how they make it)

import {Component} from 'angular2/core';

How can I achieve this behavior?


I did some files like components.ts, templates.ts etc. where I export files from current section:

export * from './menu/item';
export * from './menu/logo';
export * from './article/article';
export * from './article/sidebar';

... and then I have one main file myApp.ts where I declare modules like so:

declare module 'myapp/components' {
    export * from './application/components';
}

declare module 'myapp/templates' {
    export * from './application/templates';
}

But this file doesn't generate anything so TS build tells me errors like ...file_path...(4,9): error TS2305: Module ''myapp/components'' has no exported member 'AlfaBeta'.

Btw. my tsconfig.json looks like this:

{
    "compilerOptions": {
        "target": "ES5",
        "module": "system",
        "moduleResolution": "node",
        "sourceMap": true,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "removeComments": false,
        "noImplicitAny": false
    },
    "exclude": [
        "node_modules"
    ]
}
tenhobi
  • 1,977
  • 3
  • 23
  • 49

2 Answers2

14

In TypeScript 2.0+ there is a baseUrl and paths property in tsconfig.json that you can use.

In your case, you would want:

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "myapp/components": [
                "menu/item",
                "menu/logo",
                "article/article",
                "article/sidebar",
            ],
            "myapp/templates": [
                "templates/*" // whatever files you want to include
            ]
        }
        // etc...
    },
    // etc...
}

In baseUrl you can specify the base directory (usually the root directory of the project). This allows you to do imports from anywhere in the directory structure as if you were doing an import from the directory specified in baseUrl.

For example, with the directory structure...

folder1
    - folder2
        - file2.ts
file1.ts

...specifying a "baseUrl": "." would allow you to import file1.ts in file2.ts as if you were in the root directory by doing:

import * as File1 from "file1"; 

On top of baseUrl you can add paths. This is useful for you and it must be used with a baseUrl. In paths you can specify patterns to match and a list of files to include in that pattern. This is illustrated in the github issue like so:

"paths": {
    "pattern-1": ["list of substitutions"],
    "pattern-2": ["list of substitutions"],
    ...
    "pattern-N": ["list of substitutions"]
}

Note that this will just make it compile. I believe you'll also have to configure SystemJS in order to get this to work at runtime and that might require using a barrel file and setting the path to point to the barrel files.

You can read more about this in the github issue or read my other related answer here that also shows a pre TS 2.0 solution.

David Sherret
  • 101,669
  • 28
  • 188
  • 178
  • TypeScript 1.8.2 gives me this error when trying to use `baseUrl`: `error TS5023: Unknown compiler option 'baseUrl'.` and the GitHub issue is tagged with the 2.0 milestone. I'm guessing this didn't actually make it into 1.8. – MrHen Feb 28 '16 at 04:21
  • 1
    @MrHen yes, they changed it to 2.0 now – David Sherret Feb 28 '16 at 19:51
2

another way to use TypeScript declare module as below:-

create a file my-module.d.ts

declare module 'my-module' {
  export default function anyName(arg1: string, arg2: string): MyResponse;
  export interface anyName {
        string: arg;
    }
}

and then import as

import * as my-module from 'my-module';