2016-07-26 79 views
0

我使用CommonJS模塊約定,因爲我將node.js作爲測試目標,並使用browserify創建單個.js文件。目前我的模塊是循環依賴的。我想要做的是指示模塊value取決於模塊pnode,但僅在編譯時。即任何運行時依賴性都應該標記爲錯誤。例如。如果模塊pnode聲明瞭類型T,那麼在模塊value中,我希望像var a : pnode.T這樣的聲明可以無誤地編譯,但是像new pnode.T()a instanceof pnode.T這樣的表達式可能會出錯,因爲它們會創建運行時相關性。Typescript。我可以區分編譯時和運行時依賴

有沒有辦法做到這一點?

動機:目前pnodevalue是循環依賴的。沒關係,只要在運行時沒有循環依賴。運行時的循環依賴會導致一個問題,因爲node.js不能正確處理它,甚至不會警告它。我當前的代碼看起來像這樣

文件pnode.ts

import value = require('./value') ; 

module pnode { 

    export abstract class Label { 
    } 
    export class LambdaLabel { 
     step() { 
      return new value.ClosureV(this) ; 
     } 
    } 
} 

export = pnode ; 

文件value.ts

import pnode = require('./pnode') ; // Would like to avoid this. 

module value { 

    export class ClosureV { 

     constructor(func : pnode.Label) { 

      if (func instanceof pnode.Label) // Would like an error here. 
       console.log("a") ; else console.log("b") ; 
     } 
    } 
} 

export = value; 

我已經試過。我希望用

/// <reference path="pnode.ts" /> 

更換線

import pnode = require('./pnode') ; // Would like to avoid this. 

可能做的伎倆,但事實並非如此。我已經考慮過多種方法來消除編譯時循環依賴,所以這是我的後退選項。當你引用它

declare module pnode { 
    abstract class Label { 
    } 
    class LambdaLabel { 
     step(): any; 
    } 
} 
export = pnode; 

然後:

+2

您可以使編譯器輸出模塊的'.d.ts'文件,然後引用'value.ts'中的'pnode.d.ts'。這樣你就告訴編譯器「這些定義是可以的,並且會在運行時出現」。另一種選擇是將所有共享類型從這些文件移動到第三個文件,比如'shared',然後這兩個模塊都會引用'shared',並且避免循環依賴。 –

+0

@NitzanTomer謝謝。聽起來很有希望。我生成了pnode.d.ts,刪除了'import pnode = require('./ pnode');',並在其位置添加了'/// '。但是現在我在使用'pnode.Label'的時候出現錯誤。錯誤是'無法找到命名空間'pnode'' –

回答

0

如果編譯pnode.ts與聲明標誌,你會得到這個.d.ts文件

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

module value { 
    export class ClosureV { 
     constructor(func : pnode.Label) {} 
    } 
} 

你會得到你所描述的錯誤:Cannot find namespace 'pnode'
這是因爲編譯器知道這個.d.ts文件代表CommonJS模塊,因爲它以export = pnode;結尾。

如果您刪除該行(或將其註釋掉),則錯誤消失。你需要在每次編譯後刪除這一行(或者有一個腳本可以幫你完成),但它會起作用。

在任何情況下,我相信擁有第三個模塊作爲其他模塊的共享模塊將給您更多的靈活性,因爲您還可以擁有在運行時可用的通用類/函數。
更不用說,編譯後不需要再採取其他操作。

+0

我無法得到這個工作。我在這個答案中重寫了'value.ts',除了'pnode.d.ts'而不是'temp.d.ts'並且保持了違規的運行時相關性。然後我用'tsc --module commonjs --moduleResolution節點--declaration pnode.ts'編譯pnode來生成.d.ts文件。接下來,我從pnode.d.ts中刪除了'export ='行。最後編譯'tsc --module commonjs --moduleResolution節點value.ts'。但是這給了'func'參數聲明中的'Can not find namespace'pnode'.'。 –

+0

我不知道爲什麼這不適合你。你正在使用哪個版本的TSC?我有'1.8.10',它工作。還有一件事我必須做才能使它工作,當我的'value.ts'有一個'pnode'的引用時,我無法編譯'pnode.ts',它的錯誤是:'無法寫入文件值。 d.ts,因爲它會覆蓋輸入文件。所以我不得不改變'require(pnode)',編譯'pnode',改變'value.ts'來引用'pnode.d.ts',然後(在刪除導出行後)它就起作用了。 –