下面列出了在使用TypeScript语言和编译器期间,经常会遇到的一些常见错误。
解决方案: 检查文件编码为UTF-8 - https://typescript.codeplex.com/workitem/1587
解决方案:检查模块路径是大小写敏感- https://typescript.codeplex.com/workitem/2134
除了传统的面向对象OO层级关系以外,利用可重用组件来构建类的另外一种流行方式是将更简单的局部类(simpler partial classes)组合来构建。你可能熟悉类似Scala语言中mixins或traits思想,这种模式已经在JavaScript中开始流行。
下面代码展示了TypeScript中如何建模mixins,然后我们来分析这段代码是如何工作的。
// Disposable Mixin
class Disposable {
isDisposed: boolean;
dispose() {
this.isDisposed = true;
}
}
// Activatable Mixin
class Activatable {
isActive: boolean;
activate() {
this.isActive = true;
}
deactivate() {
this.isActive = false;
}
}
class SmartObject implements Disposable, Activatable {
constructor() {
setInterval(() => console.log(this.isActive + " : " + this.isDisposed), 500);
}
interact() {
this.activate();
}
// Disposable
isDisposed: boolean = false;
dispose: () => void;
// Activatable
isActive: boolean = false;
activate: () => void;
deactivate: () => void;
}
applyMixins(SmartObject, [Disposable, Activatable])
var smartObj = new SmartObject();
setTimeout(() => smartObj.interact(), 1000);
////////////////////////////////////////
// In your runtime library somewhere
////////////////////////////////////////
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
derivedCtor.prototype[name] = baseCtor.prototype[name];
})
});
}
代码例子一开始是两个类,角色就是mixins。可以看出每个类聚焦于一个特定的活动或能力。后面我们将它们混合在一起(mix these together)形成一个有两种能力的新类。
// Disposable Mixin
class Disposable {
isDisposed: boolean;
dispose() {
this.isDisposed = true;
}
}
// Activatable Mixin
class Activatable {
isActive: boolean;
activate() {
this.isActive = true;
}
deactivate() {
this.isActive = false;
}
}
接下来,我们将这两个mixins组合为一个新类,下面看看如何做到:
class SmartObject implements Disposable, Activatable {
上面代码中第一会注意到没有用'extends', 而是用的'implements'关键字。这将类当做接口,只是用了Disposable与Activatable后面的类型而没有用实现。这意味着我们必须提供类中的实现。Except, that's exactly what we want to avoid by using mixins.
为了满足这个需求,就需要在新类中创建在mixins中的替代者属性(stand-in properties)与成员类型。这样可以让编译器知道在运行时这些成员是存在的。这样我们可以得到mixins的好处,尽管需要付出一些记录代价(bookkeeping overhead)。
// Disposable
isDisposed: boolean = false;
dispose: () => void;
// Activatable
isActive: boolean = false;
activate: () => void;
deactivate: () => void;
接下来,将mixins混合到类中,创建完整的实现。
applyMixins(SmartObject, [Disposable, Activatable])
最后, 创建一个helper函数来做混合。这将遍历mixins的每个属性,并复制到mixins的target类中,用实现来填充这些替代者属性(filling out the stand-in properties with their implementations)。
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
derivedCtor.prototype[name] = baseCtor.prototype[name];
})
});
}
[1] http://www.typescriptlang.org/Handbook#common-errors
[2] TypeScript系列1-简介及版本新特性, http://my.oschina.net/1pei/blog/493012
[3] TypeScript手册翻译系列1-基础类型, http://my.oschina.net/1pei/blog/493181
[4] TypeScript手册翻译系列2-接口, http://my.oschina.net/1pei/blog/493388
[5] TypeScript手册翻译系列3-类, http://my.oschina.net/1pei/blog/493539
[6] TypeScript手册翻译系列4-模块, http://my.oschina.net/1pei/blog/495948
[7] TypeScript手册翻译系列5-函数, http://my.oschina.net/1pei/blog/501273
[8] TypeScript手册翻译系列6-泛型, http://my.oschina.net/1pei/blog/513483