TypeScript absolute import from other project for normal TS files and global scope declarations

Viewed 1270

I am evaluating a migration to TypeScript for a large code base in an JavaEE environment. There are multiple projects with deep directory structures and JavaScript code that uses global variables etc. across the projects.

TypeScript has multi-project support, illustrated by this small example on GitHub. However, my case is more complex.

(1) JS code is placed deep inside the projects, for example "Project1/src/main/resources/de/mycompany/webapp/ts". The generated JS code should then be place in "Project1/src/main/resources/de/mycompany/webapp/ts-generated". TypeScript offers rootDir and outDir for this purpose.

(2) The folder structure is complex, which is why relative imports are not an option. For example, referencing a file from core project should always be the same - no matter if done from ui project or ui-utils project. TypeScript offers "baseUrl" and "paths" for absolute references. However, this does not seem to work with multi-project setup (or I do something wrong). For example, I want to import * from '@core/utils/mycode.ts'. This reference should be interpreted relative to the core project's baseUrl or rootDir.

(3) I have to make references to existing JS code in global scope. For this purpose, TypeScript offers declaration files (.d.ts) that can be used to give additional type information to the compiler. Thus, I plan to create declaration files for existing JS code. The declarations then have to be imported by consuming TypeScript projects. However, the import-keyword in TypeScript seems to always import declarations as module with a namespace, which contradicts the fact that the JS objects are bound to global scope. I also found Triple-Slash import, which seems to work for relative references but not with absolute references to other projects.

Questions

For (2): Is it possible to have absolute imports across projects, preferably from the baseUrl or rootDir?

For (3): Is it possible to import (or reference) TypeScript declarations from other projects for JS code in global scope. Note that this should not generate any code, it should just tell the compiler about existing code.

1 Answers

Regarding (3)

To include global scope type declarations (.d.ts files), TypeScript offers "typeRoots" array in tsconfig.json: "typeRoots" : ["./typings"]. Note that these files must also be available from paths in the "include" array ("include": ["./typings/*.ts"]).

This works because the paths in "typeRoots" and "include" can also point to a directory outside the current project.

Regarding (2)

This does not seem to be possible with a single call to the TypeScript compiler. However, it is possible when compiling the projects one after another in the order of their dependencies.

Thus, I assume that a project P1 without dependencies has been compiled already. Now the goal is to compile the project P2, which uses code from P1. For the following example, the "outDir" of P1 is assumed to be "build":

  • Include all ts files from the "outDir" of P1 via the "includes" array of P2.
    • "include": ["../P1/build/*.ts"]
    • This will make the compiled d.ts files from P1 available in P2 such that the TypeScript compiler has knowledge of the code from P1.
  • Add a path alias to the "outDir" of P1 via the "paths" array of P2.
    • "paths": { "@P1/*": ["../P1/build/*"] }
    • This will make absolute imports work.

This works because the paths in "paths" and "includes" array can point to a directory outside the current project.

Note that this solution does not make use of Project References feature of TypeScript. Note further that no typeRoots are needed, except when you want to provide type information for plain JS code. Otherwise the type information should already be found in the "outDir" of P1

Related