跨CommonJS模块的Typescript继承-循环依赖 [英] Typescript Inheritance across CommonJS modules - Circular Dependencies
问题描述
我无法在使用打字稿1.0( tsc
使用-module commonjs
)
当两个继承相同基类的类彼此通过基类相互调用时,此操作将失败。
似乎发生的现象是,第一类导入了基类,第二类也导入了基类,但最后一次基类导入失败。
下面提供了一个说明这种行为的示例。
Typescript或CommonJS规范中是否有任何内容阻止我执行此操作,或者这是一个错误?
===示例===
这个引人入胜的软件失败了运行 Lower.test.ts
。它只是试图实现的目的是将一个单词加载到 Lower
中,使其保持小写,然后使用继承的 toUpper()$ c $
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>
问题已得到很好的记录,并提出了各种解决方案:
不幸的是,控制很少关于可以在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 (tsc
is 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:
- Exporting before
requiring
: here - Delaying the
require
or using injection: here - 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屋!