【问题标题】:TypeScript class interface definitionTypeScript 类接口定义
【发布时间】:2015-07-27 15:13:22
【问题描述】:

我正在尝试为第三方库创建定义文件 (*.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();
    }
}    

我目前拥有的一种解决方法是创建一个 TypeScript 文件 (*.ts),它定义了一个 class 而不是 interface,其中包含具有空主体或返回虚拟值的基本类型中的所有方法。然后,用户类可以从此 extend 进行类型检查。但是,这看起来真的很hacky,并导致不必要的和潜在危险的原型操作。有没有更好的办法?

TypeScript.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();
    }
}

更新

事实上,我确实在使用空存根函数进行扩展时遇到了一些麻烦。所以,我的新解决方法只是创建一个存根以使投射更容易......

TypeScriptd.ts文件定义第三方库基类:

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

TypeScript .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();
    }
}  

【问题讨论】:

  • 对于那些好奇的人,我正在处理的一个特定库是用于 Google 的 Polymer 0.9
  • 那里的聚合物选项没有移植到 0.9。此外,它并没有真正提供创建适当的 TypeScript 类以传递给具有用于处理用户方法中的 this 上下文的类型的注册。

标签: types typescript


【解决方案1】:

您应该使用环境声明。这提供了类型信息,但不会在 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();

【讨论】:

  • 谢谢,但这不起作用。我可以定义抽象类Base,是的。但是当用户类尝试implement Base 时,TypeScript 会抱怨缺少third_party_base_method
  • 您可能需要发布另一个问题,因为它在这里有效:bit.ly/1eanPkc
  • 通过使用extends otherlib.Base 它确实可以编译。但是,这样做的问题是,当您实际创建一个 MyClass 对象时,编译的 JavaScript 会尝试实际扩展基于 otherlib.Base 的原型。这会导致运行时失败,因为第三方库不是为了以这种方式创建对象而构建的。它使用显然与此不同的一些不同约定来构建和扩展它们自己。我还尝试使用其他任意未使用的命名空间进行环境描述。但是,当然,extends 在运行时也会失败,因为它没有定义。
  • 感谢您的更新!我敢肯定,这在某些情况下会有所帮助。但是,尝试获取这些类型的目的是让 MyClass 或 Example 中的用户方法可以访问具有正确类型的第三方方法,而不仅仅是构造对象的用户。这个库实际上并没有一个明确的工厂来返回要转换的对象。我确实使用强制转换的解决方法为问题添加了更新。
猜你喜欢
  • 2020-11-24
  • 1970-01-01
  • 1970-01-01
  • 2020-05-19
  • 2019-06-09
  • 2019-10-11
  • 2021-01-24
  • 2021-06-19
相关资源
最近更新 更多