使用 TypeScript 在现有原型上扩展实例/静态函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16816414/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Extending instance/static functions on existing prototypes with TypeScript
提问by Matthew Layton
I recently asked a question about TypeScript's ability to extend existing prototypes in the JavaScript API (here: Extending Object.prototype with TypeScript).
我最近问了一个关于 TypeScript 在 JavaScript API 中扩展现有原型的能力的问题(这里:用 TypeScript 扩展 Object.prototype)。
This turned out to be a bug, which has since been resolved as of TypeScript 0.9.0 Alpha (which now includes generics...GREAT :-))
结果证明这是一个错误,自 TypeScript 0.9.0 Alpha 起已解决(现在包括泛型......很棒:-))
In TypeScript, interfaces are open ended, so if you look in lib.d.ts, you will find an interface which defines the contract for JavaScript's Object API. You should also see a variable declaration for Object, which defines Object's static functions.
在 TypeScript 中,接口是开放式的,所以如果你查看lib.d.ts,你会发现一个接口定义了 JavaScript 的对象 API 的契约。您还应该看到 Object 的变量声明,它定义了 Object 的静态函数。
For the sake of simplicity, here they are:
为了简单起见,它们是:
//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[];
}
So, my previous question was about extending the interface for Object, like so:
所以,我之前的问题是关于扩展 Object 的接口,如下所示:
interface Object {
GetFoo(): Foo;
}
Object.prototype.GetFoo = function() {
return new Foo();
}
As stated, this works as of TypeScript 0.9.0.
如前所述,这适用于 TypeScript 0.9.0。
But now I also want to be able to add static functions to Object, perfectly legal in pure JavaScript.
但现在我也希望能够向 Object 添加静态函数,在纯 JavaScript 中完全合法。
In JavaScript I would do:
在 JavaScript 中,我会这样做:
Object.FooAgain = function () {
// Yes, it's foo again!
}
But I can't seem to be able to accomplish this in TypeScript.
但是我似乎无法在 TypeScript 中完成此操作。
First I tried to see if Object's declaration was open ended (as with interfaces):
首先,我尝试查看 Object 的声明是否是开放式的(与接口一样):
declare var Object: {
FooAgain(): void;
}
Object.FooAgain = function () {
// TS doesn't like this, and Object.FooAgain isn't available in intellisense.
}
I also tried (I saw this in another article, and thought it was worth a try).
我也尝试过(我在另一篇文章中看到了这个,并认为值得一试)。
export declare var Object: {
}
but this seems to break everything even more...
但这似乎更打破了一切......
Admittedly this issue may have also been fixed in TS 0.9.0 (I'm at work so I haven't actually tried it fully).
诚然,这个问题也可能在 TS 0.9.0 中得到了修复(我正在工作,所以我实际上还没有完全尝试过)。
Can anyone shed some light on this?
任何人都可以对此有所了解吗?
采纳答案by Stefan Born
Since TypeScript 1.4 static extensions can be added easily. The TypeScript team changed the lib.d.ts
file to use interfaces for all static type definitions.
由于可以轻松添加 TypeScript 1.4 静态扩展。TypeScript 团队更改了lib.d.ts
文件,以对所有静态类型定义使用接口。
The static type definitions are all named like [Type]Constructor
: So if you want to add a static function to type Object
, then add your definition to ObjectConstructor
.
静态类型定义都命名如下[Type]Constructor
: 因此,如果您想将静态函数添加到类型Object
,请将您的定义添加到ObjectConstructor
.
Definition:
定义:
interface ObjectConstructor
{
FooAgain(): void;
}
Implementation:
执行:
Object.FooAgain = function(): void
{
// Oh noes, it's foo again!
}
回答by Fenton
The problems you are encountering are the following:
您遇到的问题如下:
Declarations of variables are not open like interfaces, so you can't add properties to an existing declare var ...
.
变量声明不像接口那样开放,所以你不能向现有的declare var ...
.
Because it is declare var
and not declare class
you can't extend Object using inheritance.
因为它是declare var
而不是declare class
你不能使用继承来扩展 Object。
So you can't get the full experience from TypeScript in this scenario. You can only get the compromise of:
所以在这种情况下你无法从 TypeScript 中获得完整的体验。你只能得到以下妥协:
Object['FooAgain'] = function () {
alert('Again?');
}
Object['FooAgain']();
If you want the full TypeScript experience, I recommend you create a class to house the static methods - they don't operate on an instance anyhow, so there is little harm in doing this:
如果您想要完整的 TypeScript 体验,我建议您创建一个类来容纳静态方法 - 无论如何它们都不会对实例进行操作,因此这样做没有什么害处:
module Custom {
export class Object {
static FooAgain() {
alert('Again?');
}
}
}
Custom.Object.FooAgain();
回答by basarat
UPDATE
更新
It is now possible since TS 1.4. See Stefan's answer above
LEGACY
遗产
I have this bug raised for a while now: https://typescript.codeplex.com/workitem/917
我有一段时间提出这个错误:https: //typescript.codeplex.com/workitem/917
One solution that the typescript team could have (without extending the language spec) is have used interfaces for the static members and constructors : http://basarat.github.io/TypeScriptDeepDive/#/modellingstatics
打字稿团队可以拥有的一种解决方案(不扩展语言规范)是使用静态成员和构造函数的接口:http: //basarat.github.io/TypeScriptDeepDive/#/modellingstatics
Basically if lib.d.ts had:
基本上如果 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;
Then you could have easily added members to Object via:
然后,您可以通过以下方式轻松地将成员添加到 Object:
interface ObjectStatic {
FooAgain(): void;
}
Object.FooAgain = function () {
// TS would be fine with this.
}
I just created a feature request for this as well : https://typescript.codeplex.com/workitem/1085
我也刚刚为此创建了一个功能请求:https: //typescript.codeplex.com/workitem/1085