我最近问了一个关于TypeScript在JavaScript API中扩展现有原型的能力的问题(这里:Extending Object.prototype with TypeScript)。
这结果是一个bug,从那时起就被解决了TypeScript 0.9.0 Alpha(现在包括泛型......很棒: - ))
在TypeScript中,接口是开放式的,因此如果查看 lib.d.ts ,您将找到一个定义JavaScript的Object API合约的接口。您还应该看到Object的变量声明,它定义了Object的静态函数。
为简单起见,这里是:
//Pulled from lib.d.ts
interface Object {
toString(): string;
toLocaleString(): string;
valueOf(): Object;
hasOwnProperty(v: string): bool;
isPrototypeOf(v: Object): bool;
propertyIsEnumerable(v: string): bool;
[s: string]: any;
}
declare var Object: {
new (value?: any): Object;
(): any;
(value: any): any;
prototype: Object;
getPrototypeOf(o: any): any;
getOwnPropertyDescriptor(o: any, p: string): PropertyDescriptor;
getOwnPropertyNames(o: any): string[];
create(o: any, properties?: PropertyDescriptorMap): any;
defineProperty(o: any, p: string, attributes: PropertyDescriptor): any;
defineProperties(o: any, properties: PropertyDescriptorMap): any;
seal(o: any): any;
freeze(o: any): any;
preventExtensions(o: any): any;
isSealed(o: any): bool;
isFrozen(o: any): bool;
isExtensible(o: any): bool;
keys(o: any): string[];
}
所以,我之前的问题是关于扩展Object的接口,如下所示:
interface Object {
GetFoo(): Foo;
}
Object.prototype.GetFoo = function() {
return new Foo();
}
如上所述,这适用于TypeScript 0.9.0。
但是现在我也希望能够向Object添加静态函数,在纯JavaScript中完全合法。
在JavaScript中我会这样做:
Object.FooAgain = function () {
// Yes, it's foo again!
}
但我似乎无法在TypeScript中完成此任务。
首先,我试着看看Object的声明是否是开放的(与接口一样):
declare var Object: {
FooAgain(): void;
}
Object.FooAgain = function () {
// TS doesn't like this, and Object.FooAgain isn't available in intellisense.
}
我也尝试过(我在另一篇文章中看到了这一点,并认为值得一试)。
export declare var Object: {
}
但这似乎打破了一切......
不可否认,这个问题也可能已经在TS 0.9.0中修复了(我正在工作,所以我还没有完全尝试过它。)
任何人都可以对此有所了解吗?
答案 0 :(得分:14)
因为可以轻松添加TypeScript 1.4静态扩展。 TypeScript团队更改了lib.d.ts
文件,以便为所有静态类型定义使用接口。
静态类型定义的名称都与[Type]Constructor
类似:因此,如果要添加静态函数以键入Object
,请将定义添加到ObjectConstructor
。
定义:
interface ObjectConstructor
{
FooAgain(): void;
}
实现:
Object.FooAgain = function(): void
{
// Oh noes, it's foo again!
}
答案 1 :(得分:3)
您遇到的问题如下:
变量声明不像接口那样打开,因此您无法向现有declare var ...
添加属性。
因为它是declare var
而不是declare class
,所以无法使用继承来扩展Object。
因此,您无法在此方案中获得TypeScript的完整体验。你只能得到妥协:
Object['FooAgain'] = function () {
alert('Again?');
}
Object['FooAgain']();
如果你想要完整的TypeScript体验,我建议你创建一个容纳静态方法的类 - 它们无论如何都不能在实例上运行,所以这样做没有什么害处:
module Custom {
export class Object {
static FooAgain() {
alert('Again?');
}
}
}
Custom.Object.FooAgain();
答案 2 :(得分:3)
现在可以从TS 1.4开始。请参阅Stefan的answer below
我现在提出这个错误了一段时间:https://typescript.codeplex.com/workitem/917
打字稿团队可以拥有的一个解决方案(不扩展语言规范)是使用静态成员和构造函数的接口:http://basarat.github.io/TypeScriptDeepDive/#/modellingstatics
基本上如果lib.d.ts有:
//Pulled from lib.d.ts
interface Object {
toString(): string;
toLocaleString(): string;
valueOf(): Object;
hasOwnProperty(v: string): bool;
isPrototypeOf(v: Object): bool;
propertyIsEnumerable(v: string): bool;
[s: string]: any;
}
interface ObjectStatic {
new (value?: any): Object;
(): any;
(value: any): any;
prototype: Object;
...
}
declare var Object: ObjectStatic;
然后您可以通过以下方式轻松地将成员添加到Object:
interface ObjectStatic {
FooAgain(): void;
}
Object.FooAgain = function () {
// TS would be fine with this.
}
我刚刚为此创建了一个功能请求:https://typescript.codeplex.com/workitem/1085