簡體   English   中英

TypeScript裝飾器和循環依賴項

[英]TypeScript Decorators and Circular Dependencies

考慮一下使用修飾符的相互依賴的代碼示例(如下)。

現在考慮以下工作流程(是的,我確實想傳遞實際的導出類,因為以后需要使用它們):

  1. 應用程序導入並運行Parent.ts
  2. @Test(Child)使應用程序在裝飾時導入Child.ts
  3. 注意:代碼尚未到達Parent
  4. Child.ts ,執行@Test(Parent)裝飾器
  5. 此時, Parent是未定義的,無法傳遞給裝飾器。

如您所見,有一個令人討厭的循環依賴,並且我看不到能夠應用將類作為彼此引用的參數的裝飾器的方法。

請注意,為簡便起見,我以@Test為例。 實際的裝飾器是@HasMany@BelongsTo所以我在這里有一個實際的用例。

我對您的問題: “是否有解決此問題的方法?”

我擔心的是,除非TypeScript的編譯代碼被更改以將修飾過程推遲到所有相關代碼都被導入之前,否則沒有。

代碼示例:

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 {

    }

今天遇到同樣的問題。 我通過將@Test(() => Parent)替換為@Test(Parent)來解決問題。

我沒有跟蹤元數據中的類構造函數( Parent ),而是跟蹤返回構造函數( () => Parent )的thunk。 這將延遲對Parent導入變量的求值,直到調用thunk為止,從而達到目的。

如果可以推遲在裝飾器中執行的操作-您可以克服此限制並打破循環依賴關系。 從真正的裝飾器的名稱@HasMany和@BelongsTo看來,您正在將某種元數據附加到每個類中供以后使用-如果是這樣,這是我的建議:

  1. 擴展@Test裝飾器簽名

export function Test(passedClass: Function | string)

我在這里假設裝飾器會將元信息存儲在某種靜態字典中,例如:。 屬性看起來像哪里

{
    hasMany: {new(): any} | string
    belongsTo: {new(): any} | string
}
  1. 在裝飾器內部,將hasMany / belongsTo屬性設置為passedClass以創建新的屬性對象。 如果passedClass不是字符串,請檢查所有已添加的屬性,並替換所有字符串類型且當前等於passedClass.name hasMany / passedClass.name

  2. 從父級刪除對子級的引用。

這是有點天真的實現,您可以實現一些私有字段,而不是隱藏中間字符串數據,並避免暴露聯合類型字段。

希望這會幫助你。

怎么做,但是結構不同呢?
如果ChildParent都駐留在同一個文件中,那應該沒有問題。

這聽起來可能不是最佳的,因為由於長度和邏輯的原因,很容易將代碼分離為模塊,但這可以通過某種方式解決。
您可以擁有一個包含這些基本類(甚至是抽象類)的主文件:

// Base.ts
import {Test} from "./Decorators";

@Test(BaseChild)
export abstract class BaseParent {}

@Test(BaseParent)
export abstract class BaseChild {}

然后在您的特定模塊中:

// Parent.ts
import {BaseParent} from "./Base";

export class Parent extends BaseParent {}

// Child.ts
import {BaseChild} from "./Base";

export class Child extends BaseChild {}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM