Circular Type References in TypeScript

I am new to typescript and am trying to understand how I can setup a circular reference between two types. The reference need not be a full code reference, simply the interfaces, but with interfaces defined in separate files. For example, let's say I have two interfaces: Parent and Child. They are doubly-linked such that the parent has a collection of children and each child has a reference to the parent (as seen below). How do I setup the imports or dependencies so that these can be defined in separate files?

interface Parent {
  children: Child[]
}

interface Child {
  parent: Parent
}

Solution 1:

I also faced with the similar situation.

I could resolve by using import type.

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html

Solution 2:

Two solutions below. I prefer the latter since it offers clean interfacing with Node JS modules, but unfortunately my IDE doesn't (yet) like it as much as I do...

Use references

Create a definitions.d.ts file that will only contain the references to your classes/interfaces

/// <reference path="Parent.ts" />
/// <reference path="Child.ts" />

In Parent.ts and Child.ts, point to a single reference, the definitions.d.ts file

/// <reference path="definitions.d.ts" />

Use import...require

pass the --module commonjs flag to tsc then import what you require and export what you want to expose

In Parent.ts

 import Child = require('Child')

 interface Parent { 
     children: Child[]
 }

 export = Parent

In Child.ts

 import Parent = require('Parent')
 
 interface Child {
     parent: Parent
 }

 export = Child

Please note, that you do not specify the extension '.ts' in require

Solution 3:

I have about 10 ts files , in a Circular-Dependency-Hell .

The common methods can't help me any more , because the dependencies relation between 10 files is to complex.

At finally , I solved it. Using following 2 methods :

  1. Install repo ———— "circular-dependency-plugin": "5.0.2"

    This repo will helps me to find the place where circular occurs.

  2. Using a designed internal.ts , to manage my import & export

    I tried the method of this article :

    How to fix nasty circular dependency issues once and for all in JavaScript & TypeScript

    This amazing article tells me to create internal.ts .

    and using like export * form 'file-A' ; export * from 'file-B' to manage my circular dependencies.

    It works very well when I use dependencies related to my 10 files, like this import classA from '../internal.ts'.

————————————————————————————————————

If the above method has no effect on you, I found another general solution:

Use

const File_Promise = import ('yourFilePath')" to import other file or module .

when you need to use this one, use

File_Promise.then (file => { file.xxx(file.yyy) }) , just like using Promise syntax. `

This will break the Circular-Dep Chain !

If i am you , I will continue this action until NO ERROR Reported by "circular-dependency-plugin".

————————————————————————————————————

Hope to help YOU !