4

Я использую TypeScript с --module system (SystemJS) в очень большом проекте. SystemJS поддерживает циклические зависимости, и большую часть времени он отлично работает. Тем не менее, когда наследование типа TypeScript задействовано, все начинает ломаться.Наследование типов TypeScript и круговые зависимости в SystemJS

Например, если class A зависит от class B и class Bнаследует от class A, а затем, если class A загружается первый:

  1. Это приостановит решение class A's и будет пытаться загрузить class B зависимость
  2. class B будет думать, что его зависимости решены, так как был затронут class A.
  3. class B's Наследование не будет разрешено, потому что class A по-прежнему не определено.

Большинство «решений» можно найти на веб-сайте в циклическими зависимостями с модулем погрузчикам либо:

  • Изменить дизайн/объединить классы в одном модуле
  • CommonJS и не- Специфические обходные методы TypeScript

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

Есть ли какие-либо решения реальной проблемы?

ответ

6

Изменение дизайна - наиболее выгодное решение. Класс не должен зависеть от его подклассов. Если вы используете их на заводе или около того, это отдельная проблема и должна идти в отдельном классе/функции/модуле.

Есть ли какие-либо решения реальной проблемы?

Как вы сказали, проблема возникает только при первом загрузке модуля A. Решение состоит в том, чтобы предотвратить это, и написать дополнительный модуль, который действует как прокси-сервер для A и всех его подклассов при импорте их в правильном порядке.

0

В этом случае я предлагаю удалить зависимость A -> B, создав отдельный интерфейс I. И A, и B необходимо знать I, а B необходимо его реализовать.

Во время процесса загрузки B должен сказать A где найти конструктор или завод по I (реализованный B).Это оставит вас с этими зависимостями:

A -> I 
B -> I 
B -> A 

Интерфейс I может выглядеть следующим образом:

interface I { 
    bFoo(): void; 
} 

export default I; 

Class A может выглядеть следующим образом:

import I from "./i"; 

class A { 
    private static __ICtor : new() => I; 
    public static setIConstructor(ctor: new() => I) { 
    A.__ICtor = ctor; 
    } 

    private __atSomePoint() : I { 
    return new A.__ICtor(); 
    } 
} 

export default A; 

И наконец class B:

import I from "./i"; 
import A from "./a"; 

class B extends A implements I { 
    public bFoo() {} 
} 

A.setIConstructor(B); 

IMHO это решит вашу циклическую зависимость, даже если уже слишком поздно.

0

Там аккуратный способ решить эту проблему с помощью преобразования Бабеля плагина здесь: https://github.com/zertosh/babel-plugin-transform-inline-imports-commonjs

Что она делает это преобразует в-старт-из-файла импорта модуля в инлайн требует, только на самом деле импорта/требуют другие модули перед их использованием.

В большинстве случаев это автоматически решает проблему, так как к тому моменту, когда на самом деле выполняется какой-либо класс-код, все модули завершили свой экспорт.


Обратите внимание, что по умолчанию плагин, указанный выше, применяется ко всем импортам в вашем проекте, поэтому требуется их включение в встроенную строку. Тем не менее, более серьезная проблема заключается в том, что я не смог найти встроенный способ заставить его работать с импортными/относительными маршрутами.

Я установил обе эти проблемы в моей вилке проекта здесь: https://github.com/Venryx/babel-plugin-transform-inline-imports-commonjs

Я сделал запрос тянуть за эти изменения, но он ожидает рассмотрения атм.

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