2015-05-15 328 views
2

我试图为第三方库创建一个定义文件(*.d.ts)。这个库有一个基类,用户对象最终将继承它。但是,库处理这些对象的构造,并将它们自己的内置方法与用户定义的方法合并。因此,我不能只创建一个用户类implementsinterface,因为用户类未定义基类的内置方法。TypeScript类接口定义

打字稿定义d.ts文件:

module otherlib { 
    export interface Base { 
     third_party_base_method(): string; 
    } 
} 

用户源:

// FAILS because MyClass doesn't define third_party_base_method() 
class MyClass implements otherlib.Base { 
    myfunc() { 
     let str = this.third_party_base_method(); 
    } 
}  

一种解决方法我现在有是创建一个打字稿文件(*.ts),其限定了class而不是一个interface与所有基体类型中具有空体或返回虚拟值的方法。用户类然后可以从extend这样的类型检查工作。但是,这看起来很不方便,导致不必要的和潜在危险的原型操作。有没有更好的办法?

打字稿.ts文件来定义第三方库的基类:

module otherlib { 
    export class Base { 
     // Dummy stub definition that is never called 
     third_party_base_method(): string { return "dummy"; } 
    } 
} 

用户来源:

class MyClass extends otherlib.Base { 
    myfunc() { 
     // Proper type checking for calling the method that the 
     // third party library adds to the object. 
     let str = this.third_party_base_method(); 
    } 
} 

UPDATE

我其实开始碰到一些与空的存根函数一起扩展的麻烦。所以,我的新的解决方法就是建立一个存根,使铸件容易...

打字稿d.ts文件来定义第三方库的基类:

module otherlib { 
    export interface Base { 
     third_party_base_method(): string; 
    } 
} 

打字稿.ts文件铸造存根:

module otherlib_stub { 
    export class Base { 
     get base(): otherlib.Base { return <otherlib.Base><any>this; } 
    } 
} 

用户来源:

class MyClass extends otherlib_stub.Base implements otherlib.Base { 
    myfunc() { 
     // Proper type checking for calling the method that the 
     // third party library adds to the object. 
     let str = this.base.third_party_base_method(); 
    } 
} 
+0

对于那些好奇的人,我正在处理的特定图书馆是Google的Polymer 0.9 – drarmstr

+0

您是否知道Definitely Typed? https://github.com/borisyankov/DefinitelyTyped/tree/master/polymer – Fenton

+0

聚合物在那里的选项没有被移植到0.9。另外,它并没有真正提供创建一个适当的TypeScript类来传递给用户方法中用于处理此上下文的键入。 – drarmstr

回答

0

你守ld使用环境声明。这提供了类型的信息,但不会产生在JavaScript输出的任何代码:

declare module otherlib { 
    export class Base { 
     third_party_base_method(): string; 
    } 
} 

你可以把这个与.d.ts扩展名的文件,使之清楚,这不是一个实现文件。

更新!

这取决于第三方库的工作方式,但您可以使用接口将外部成员和本地成员包装为单一类型。

下面的例子假设你调用一个返回你的扩展类的方法。如果您需要帮助确定其确切版本,您将不得不提供一个实际工作方式的示例。

declare module otherlib { 
    export interface Base { 
     third_party_base_method(): string; 
    } 

    export function externalCodeThatExtendsYourClass<T>(obj: any): T; 
} 

// You would need the class/interface pair for each class 
class Example { 
    yourMethod() { 
     alert('All yours'); 
    } 
} 

// The interface wraps the class members and the externally added members into a single type 
interface ExtendedExample extends Example, otherlib.Base { } 


var example = otherlib.externalCodeThatExtendsYourClass<ExtendedExample>(new Example()); 

example.third_party_base_method(); 
example.yourMethod(); 
+0

谢谢,但这没有奏效。我可以定义抽象类Base,是的。但是当用户类试图执行Base时,TypeScript抱怨缺少'third_party_base_method'。 – drarmstr

+0

您可能需要发布另一个问题,因为它在这里工作:http://bit.ly/1eanPkc – Fenton

+0

通过使用'扩展otherlib.Base'它确实编译。然而,问题在于,当你实际创建一个MyClass对象时,编译后的JavaScript会尝试实际扩展基于otherlib.Base的原型。由于第三方库不是以这种方式创建对象的,因此这会导致运行时失败。它构造并扩展了它们本身,显然有一些不同的约定可以打破这一点。我也尝试使用一些任意其他未使用的名称空间进行环境描述。但是,'extend'在运行时也会失败,因为它没有被定义。 – drarmstr