CommonJS模块之间的Typescript继承 - 循环依赖

时间:2014-07-07 17:55:54

标签: inheritance typescript commonjs

我无法继承使用typescript 1.0生成的CommonJS模块(tsc使用--module commonjs运行)

当两个类继承相同的基类,相互调用"通过"基类。

看起来似乎是第一类导入基类,它导入第二个类,它也导入基类但最后一个基类导入失败。

下面提供了一个说明此行为的示例。

Typescript或CommonJS规范中是否有任何内容阻止我这样做,或者这是一个错误?

===示例===

这个引人入胜的软件因运行Lower.test.ts而失败。它只是试图实现的是将一个单词加载到Lower中,使其保持小写,然后使用toUpper()类中的继承Base方法,使用{以大写形式对其进行转换{1}}类(也继承Upper

Lower.test.ts

Base

Base.ts

import Lower = require('./Lower')

console.log(new Lower('smallcaps').toUpper())

Upper.ts

import Upper = require('./Upper')

class Base {

    word: string

    toUpper(): string {
        return new Upper(this.word).word
    }
}

export = Base

Lower.ts

import Base = require('./Base')

class Upper extends Base {

    constructor(word:string) {
        super()
        this.word = word.toUpperCase()
    }
}

export = Upper

2 个答案:

答案 0 :(得分:2)

经过一些研究和测试,这最终成为循环依赖的情况。

该问题已有详细记录,并提出了各种解决方案:

  1. requiring之前导出:here
  2. 延迟require或使用注射:here
  3. 移动陈述:一个很长的列表here
  4. 不幸的是,很少有人控制在Typescript中设置importexport语句的位置,这样只会减少注入解决方案。下面提供了重写的Base课程。

    循环依赖是Javascript模块化项目的难点。打字稿不知何故让事情变得更糟。这对于一个应该解决大型项目的语言来说是个坏消息

    修改 我打开了一个案例,并向TypeScript项目提交了一个提议的转发器修复程序:here

    Base.ts

    //This import will "fail" by importing an empty object but is needed to trick the compiler
    //An alternative is to design and Upper.d.ts definition file and reference it
    import Upper = require('./Upper')
    
    class Base {
    
        //Upper is a sub-class of Base and needs to be injected to be instantiated
        private _Upper: typeof Upper
    
        word: string
    
        constructor(_Upper: typeof Upper) {
            this._Upper = _Upper
        }
    
        toUpper(): string {
            //This where the injection is used
            return new this._Upper(this.word).word
        }
    
    
        getUpperWord(upper: Upper): string {
            //The injection is not reauired in this case
            return upper.word
        }
    }
    
    export = Base
    

    Upper.ts

    import Base = require('./Base')
    
    class Upper extends Base {
    
        constructor(word:string) {
            super(Upper)
            this.word = word.toUpperCase();
        }
    }
    
    export = Upper
    

答案 1 :(得分:0)

通常最好只依赖一个方向 - 按照SOLID原则。

但是,由于您始终需要BaseUpper(即您不能拥有另一个),您可以将它们添加到同一个模块...

base.ts

export class Base {
    word: string

    toUpper(): string {
        return new Upper(this.word).word
    }
}

export class Upper extends Base {

    constructor(word: string) {
        super()
        this.word = word.toUpperCase()
    }
}

lower.ts

import b = require('base')

class Lower extends b.Base {

    constructor(word: string) {

        super()
        this.word = word.toLowerCase()
    }
}

export = Lower 

app.ts

import Lower = require('lower');

console.log(new Lower('smallcaps').toUpper());