14

我最近问了一个关于 TypeScript 在 JavaScript API 中扩展现有原型的能力的问题(这里:Extending Object.prototype with TypeScript)。

结果证明这是一个错误,自 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 中得到修复(我正在工作,所以我实际上并没有完全尝试过)。

任何人都可以对此有所了解吗?

4

3 回答 3

14

由于 TypeScript 1.4 可以轻松添加静态扩展。TypeScript 团队更改了lib.d.ts文件以使用所有静态类型定义的接口。

静态类型定义都是这样命名的[Type]Constructor:所以如果你想给 type 添加一个静态函数Object,那么把你的定义添加到ObjectConstructor.

定义:

interface ObjectConstructor
{
    FooAgain(): void;
}

执行:

Object.FooAgain = function(): void
{
    // Oh noes, it's foo again!
}
于 2015-01-19T08:54:16.623 回答
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();
于 2013-05-29T15:08:02.993 回答
3

更新

现在可以从 TS 1.4 开始。请参阅上面 Stefan 的回答

遗产

我有一段时间提出这个错误: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

于 2013-05-29T22:05:28.300 回答