Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript Decorators and Circular Dependencies

Consider the sample of inter-dependent code (below) that makes use of decorators.

Now consider the following workflow (yes, I do want to pass the actual exported classes since I need to use them later):

  1. App imports and runs Parent.ts
  2. @Test(Child) causes the app to import Child.ts while decorating
  3. Note: the class Parent has not yet been reached by the code
  4. In Child.ts, the @Test(Parent) decorator is executed
  5. At this point, Parent is undefined and cannot be passed to the decorator.

As you see, there's a nasty circular dependency going on and I cannot see a way of being able to apply decorators that take classes as arguments which reference each other.

Please note, I used @Test for brevity as an example. The actual decorators are @HasMany and @BelongsTo - so I do have an actual use case here.

My question to you: "Is there a solution to this issue?"

My fear is that there isn't, unless TypeScript's compiled code is changed so as to defer the decoration process until all involved code has been imported.

Code example:

Decorators.ts:

    export function Test(passedClass: Function): Function {
        return function (model: Function): void {
            console.log(typeof passedClass);
        };
    }

Parent.ts:

    import {Child} from "./Child";
    import {Test} from "./Decorators";

    @Test(Child)
    export class Parent {

    }

Child.ts:

    import {Parent} from "./Parent";
    import {Test} from "./Decorators";

    @Test(Parent)
    export class Child {

    }
like image 944
JDR Avatar asked Feb 07 '23 05:02

JDR


1 Answers

Hit the same problem today. I solved it slightly differently, by replacing @Test(Parent) by @Test(() => Parent).

Instead of tracking the class constructor (Parent) in metadata, I track the thunk that returns the constructor (() => Parent). This delays the evaluation of the Parent imported variable until the thunk is invoked, which does the trick.

like image 171
Bruno Jouhier Avatar answered Feb 08 '23 19:02

Bruno Jouhier