跨CommonJS模块的Typescript继承-循环依赖 [英] Typescript Inheritance across CommonJS modules - Circular Dependencies

查看:175
本文介绍了跨CommonJS模块的Typescript继承-循环依赖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法在使用打字稿1.0( tsc 使用-module commonjs )



当两个继承相同基类的类彼此通过基类相互调用时,此操作将失败。



似乎发生的现象是,第一类导入了基类,第二类也导入了基类,但最后一次基类导入失败。



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



Typescript或CommonJS规范中是否有任何内容阻止我执行此操作,或者这是一个错误?



===示例===



这个引人入胜的软件失败了运行 Lower.test.ts 。它只是试图实现的目的是将一个单词加载到 Lower 中,使其保持小写,然后使用继承的 toUpper() Base 类中的c>方法,使用 Upper 类(也继承了基本



Lower.test.ts

  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
}
}

出口=基础

Upper.ts

  import Base = require('./ Base')

类Upper Extended Base {

构造函数(word:string){
super()
this.word = word.toUpperCase()
}
}

出口=上

Lower.ts

  import Base = require('./ Base')

class下层扩展Base {

构造函数(word:string){

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

export =降低


解决方案

经过一些研究和测试,最终导致了循环依赖。 / p>

问题已得到很好的记录,并提出了各种解决方案:


  1. 出口在需要之前:在这里

  2. 延迟需求或使用注入:此处

  3. 移动语句:很长的列表此处

不幸的是,控制很少关于可以在Typescript中设置 import export 语句的位置,这仅将解决方案简化为注入。下面提供了重写的 Base 类。



循环依赖是Javascript模块化项目中的一个难题。打字稿使事情变得更糟。对于应该用于大型项目的语言来说,这是个坏消息



编辑
我已经开了一个案子,并提交了一份拟议的Transpiler修复程序到TypeScript项目:此处



Base.ts

  //此导入将通过导入空对象而失败,但需要欺骗编译器
//另一种方法是设计和定义Upper.d.ts文件,并引用该文件
import Upper = require('./ Upper')

class Base {

// Upper是Base的子类,需要被注入才能实例化
private _Upper:typeof Upper

word:string

构造函数(_Upper:typeof Upper){
this._Upper = _Upper
}

toUpper():string {
//使用注入的地方
返回新的this._Upper(this.word).word
}


getUpperWord(upper:Upper):字符串{
//在这种情况下不会重新进行注入
return upper.word
}
}

export =基础

Upper.ts

  import Base = require('./ Base')

class上层扩展Base {

构造函数(word:string){
超级(上)
this.word = word.toUpperCase();
}
}

出口=上层


I cannot get inheritance to work across CommonJS modules generated using typescript 1.0 (tscis run using --module commonjs)

This fails when two classes inheriting the same base class, call each other "through" the base class.

What seems to hapeen is that the first class imports the Base Class, which imports the second class which also imports the Base Class but the last Base Class import is failing.

An example illustrating this behaviour is provided below.

Is there anything in the Typescript or the CommonJS specifications preventing me from doing this, or is this a bug ?

=== Example ===

This fascinating piece of software is failed by running Lower.test.ts. What it simply tries to achieve is loading a word into Lower which keeps it in lower case, then using the inherited toUpper() method from the Base class, transforms it in upper case using the Upper class (which also inherits Base)

Lower.test.ts

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

Upper.ts

import Base = require('./Base')

class Upper extends Base {

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

export = Upper

Lower.ts

import Base = require('./Base')

class Lower extends Base {

    constructor(word:string) {

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

export = Lower

解决方案

After some research and testing, this ends up being a case of circular dependencies.

The issue is pretty well documented and various solutions have been proposed:

  1. Exporting before requiring: here
  2. Delaying the require or using injection: here
  3. Moving statements around: a pretty long list here

Unfortunately, there is very little control on where import and export statements can be set in Typescript which reduces solutions to injection only. The rewritten Base class is provided below.

Circular dependencies are a pain in Javascript modular projects. Typescript somehow makes things worse. That is bad news for a language supposed to address large projects

EDIT I have opened a case and submitted a proposed transpiler fix to the TypeScript project: 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

这篇关于跨CommonJS模块的Typescript继承-循环依赖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆