Using `import type` statement to fix circular dependency reference error

UPDATE: this answer is likely to become obsolete as soon as TypeScript 3.8 is released

You don't need to do anything special to import only type information from module a.

Typescript will do it for you - if the only thing module b needs form a is type information, compiled file b.js will not have require("./a") statement, that is, it will not have runtime dependency on a. Quote from typescript handbook:

The compiler detects whether each module is used in the emitted JavaScript. If a module identifier is only ever used as part of a type annotations and never as an expression, then no require call is emitted for that module.

I just tried that:

file a.ts

import { B } from "./b"

export class A {
    constructor(public name: string) {}
}

let b = new B();
b.print(new A("This is a random name"));

file b.ts

import { A } from './a';

export class B {
    print(a: A) {
        console.log(a.name);
    }
}

compile them together

tsc a.ts b.ts

Here is resulting b.js:

"use strict";
var B = (function () {
    function B() {
    }
    B.prototype.print = function (a) {
        console.log(a.name);
    };
    return B;
}());
exports.B = B;

see? there is no require("./a"), unlike a.js which contains

var b_1 = require("./b");

Most likely, the example code you posted in your question is incomplete, and real b module has runtime dependency on a - find out where it is and get rid of that, and you won't have this problem.


This is now directly possible in TypeScript 2.9.

type MyType = import('mymodule').MyType;
const myValue: import('mymodule').MyType;

As of TypeScript 3.8, use import type:

import type { SomeThing } from "./some-module.js";

export type { SomeThing };

Reference:

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-exports

Tags:

Typescript