Inheritance 跨CommonJS模块的Typescript继承-循环依赖

Inheritance 跨CommonJS模块的Typescript继承-循环依赖,inheritance,typescript,commonjs,Inheritance,Typescript,Commonjs,我无法使继承在使用typescript 1.0生成的CommonJS模块之间工作(tsc使用--module CommonJS运行) 当继承同一基类的两个类“通过”基类相互调用时,这将失败 在hapeen看来,第一个类导入基类,第二个类导入基类,第二个类也导入基类,但最后一个基类导入失败 下面提供了一个说明这种行为的示例 Typescript或CommonJS规范中是否有任何东西阻止我这样做,或者这是一个bug? ==示例=== 运行Lower.test.ts,此迷人的软件失败。它试图实现的只是

我无法使继承在使用typescript 1.0生成的CommonJS模块之间工作(
tsc
使用
--module CommonJS
运行)

当继承同一基类的两个类“通过”基类相互调用时,这将失败

在hapeen看来,第一个类导入基类,第二个类导入基类,第二个类也导入基类,但最后一个基类导入失败

下面提供了一个说明这种行为的示例

Typescript或CommonJS规范中是否有任何东西阻止我这样做,或者这是一个bug?

==示例===

运行
Lower.test.ts
,此迷人的软件失败。它试图实现的只是将一个单词加载到
Lower
中,并将其保留为小写,然后使用
Base
类中继承的
toUpper()
方法,使用
upper
类(也继承
Base
)将其转换为大写

下测试

import Lower = require('./Lower')

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

import Upper = require('./Upper')

class Base {

    word: string

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

export = Base
//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
上流社会

import Base = require('./Base')

class Upper extends Base {

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

export = Upper
import Base = require('./Base')

class Upper extends Base {

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

export = Upper
下塔台

import Base = require('./Base')

class Lower extends Base {

    constructor(word:string) {

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

export = Lower

通常最好只依赖一个方向——根据可靠的原则

但是,由于您始终需要
基础
上部
(即,如果没有另一个,则不能有一个),因此您可以将它们添加到同一模块中

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()
    }
}
下塔台

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());

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

这一问题有很好的记录,并提出了各种解决方案:

  • 在要求之前导出:
  • 延迟
    要求
    或使用注入:
  • 移动语句:一个相当长的列表
  • 不幸的是,在Typescript中设置
    import
    export
    语句的位置几乎没有控制,这使得解决方案只限于注入。下面提供了重写的
    Base

    循环依赖是Javascript模块化项目中的一个难题。打字脚本让事情变得更糟。这对于一种用来处理大型项目的语言来说是个坏消息

    编辑 我已经打开了一个案例,并向TypeScript项目提交了一个建议的transpiler修复程序:

    Base.ts

    import Upper = require('./Upper')
    
    class Base {
    
        word: string
    
        toUpper(): string {
            return new Upper(this.word).word
        }
    }
    
    export = Base
    
    //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
    
    上流社会

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

    感谢您的解决方案;我可以接受这样一个事实,即它减少了模块化,但仍然留下了一个问题。至于朝一个方向走,它并不总是有意义的:想象一下这个非常简单的几何应用程序,它实现了一个
    向量。一个
    向量
    可以通过将它乘以另一个
    向量
    来缩放,就像许多其他几何图形一样。创建一个
    Scalable
    类是有意义的,该类由
    Vector
    继承,并实现一个
    scale()
    方法,该方法以
    Vector
    作为参数。给你:继承一个在方法中使用它的一个子类的类。我仍然会避免它。如果一个向量总是可以伸缩的,为什么它是可伸缩的子类呢。如果它不能总是伸缩,它就不应该有scale方法,scale方法应该由可伸缩子类添加。