2016-07-26 3 views
0

Я использую соглашения модуля CommonJS, так как я нацелен на node.js для тестирования и использования браузера, чтобы создать один .js-файл. В настоящее время мои модули циклически зависимы. То, что я хотел бы сделать, это указать, что модуль value зависит от модуля pnode, но только во время компиляции. То есть любая ошибка во время выполнения должна быть помечена как ошибка. Например. если модуль pnode объявляет тип T, то в модуле value я хотел бы, чтобы объявление, как var a : pnode.T, компилировалось без ошибок, но выражение типа new pnode.T() или a instanceof pnode.T было бы ошибкой, потому что они создают зависимость во время выполнения.Машинопись. Могу ли я различать время компиляции и времени выполнения?

Есть ли способ сделать это?

Мотивация: В настоящее время pnode и value имеют круговую зависимость. Это нормально, если во время выполнения нет круговой зависимости. Круговая зависимость во время выполнения вызывает проблему, потому что 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; 

То, что я пытался. Я надеялся, что замена линии

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

с

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

может сделать трюк, но это не так. Существуют различные способы, с помощью которых я решил исключить круговую зависимость времени компиляции, так что это мой вариант падения.

+2

Вы можете сделать файлы компилятора '.d.ts' для своих модулей, а затем ссылаться на' pnode.d.ts' с 'value.ts'. Таким образом вы сообщаете компилятору, что «эти определения в порядке и будут присутствовать во время выполнения».Другой вариант - переместить все общие типы из этих файлов на третий, скажем, «shared», тогда оба этих модуля будут ссылаться на «shared», и вы избегаете циклической зависимости. –

+0

@NitzanTomer Спасибо. Это звучит многообещающе. Я сгенерировал pnode.d.ts, удалил 'import pnode = require ('./pnode');' и добавил '/// ' вместо этого. Но теперь я получаю сообщение об ошибке, когда используется 'pnode.Label'. Ошибка: «Не удается найти пространство имен» pnode'' –

ответ

0

Если вы собираете pnode.ts с флагом декларации вы получите этот .d.ts файл:

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

Затем, когда вы ссылаться на него:

/// <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' и сохраняя зависимость от времени выполнения. Затем я скомпилировал pnode с 'tsc -module commonjs -moduleResolution node -declaration pnode.ts', чтобы сделать файл .d.ts. Затем я удалил строку 'export =' из pnode.d.ts. Наконец, скомпилировано 'tsc --module commonjs --moduleResolution node value.ts'. Но это дало 'Can not find namespace 'pnode'.' в объявлении параметра' func'. –

+0

Я понятия не имею, почему это не работает для вас. Какую версию tsc вы используете? У меня «1.8.10», и он работает. Еще одна вещь, которую я должен был сделать, чтобы заставить ее работать, я не смог скомпилировать 'pnode.ts', когда у моего' value.ts' была ссылка на 'pnode', с ошибкой:' невозможно записать значение файла. d.ts, потому что он будет перезаписывать входной файл'. Поэтому мне пришлось перейти на 'require (pnode)', компилировать 'pnode', change' value.ts', чтобы ссылаться на 'pnode.d.ts', а затем (после удаления строки экспорта) сработало. –

Смежные вопросы