【问题标题】:Extend a class from an external library with a static function in a typesafe manner in TypeScript在 TypeScript 中以类型安全的方式使用静态函数从外部库扩展类
【发布时间】:2016-10-13 12:06:25
【问题描述】:

我想用 static 函数扩展 rxjs5 Observable 类。我可以用纯 JavaScript 做到这一点:

var myStaticFn = function() { /* ... */ };
Observable.myStaticFn = myStaticFn;

这可行,但在 TypeScript 中我无法访问 Observable.myStaticFn,因为 myStaticFn 在类 Observable 上是未知的。

如何声明/增加 rxjs5 Module Observable 类,以便以类型安全的方式访问我的函数?

注意:作为一个起点,下面展示了如何将一个非静态函数扩展到 Observable(例如创建一个自定义的 rxjs Operator)的示例,这完全有效,但不是我想要的!

function myOperator(this: Observable<any>): Observable<any> = function(){ /*...*/ };
Observable.prototype.myOperator = myOperator;

declare module "rxjs/Observable" {
    interface Observable<T> {
        myOperator: typeof myOperator;
    }
}

上述方法有效,因为 TypeScript 的 declare 语法允许我将 Observable 视为接口,并且可以扩充/合并接口。但是 TypeScript 没有办法在接口上声明 static 函数。

Observable 类派生也是不可行的,比如ExtendedObservable,因为我的代码的每个用户都必须在整个项目中使用ExtendedObservable 类型而不是Observable 类型,以及这个概念如果我想在 Observable 上放置不同的静态方法,也会失败,具体取决于导入的模块。

【问题讨论】:

标签: javascript typescript static rxjs rxjs5


【解决方案1】:

我发现自己在看at the implementation of the static .from() extension in the RxJS source:

import { myStaticFn as myStaticFnStatic } from "./myStaticFn";

declare module "rxjs/Observable" {
    namespace Observable {
        let myStaticFn: myStaticFnStatic;
    }
}

请注意我如何导入 myStaticFn,但将其范围限定为名称 myStaticFnStatic - 这是必需的,否则会出现编译器错误。

【讨论】:

  • Dyna 这正是我的解决方案,正如我所提到的,微软已将术语“内部模块”更改为“命名空间”。
【解决方案2】:

在 rx 的定义文件中,您有 Observable 类和 ObservableStatic 的定义。
如果要添加静态函数,则需要扩充ObservableStatic

declare module "rxjs/Observable" {
    interface ObservableStatic {
        myOperator: typeof myOperator;
    }
}

【讨论】:

  • 不幸的是,这只适用于 rxjs v
  • 好像新版本完全是用typescript重写的,而且没有定义文件,你大概是用源码吧?
  • 不,我正在使用 CommonJS 模块,该模块对每个 *.ts 文件都有类型注释,即 TS 编译使用的 node_modules/rxjs/Observable.d.ts
【解决方案3】:

你需要声明一个与接口同名的模块。在模块内部,您编写静态函数。这是 TypeScript 中的最佳实践。这叫做“模块合并”。

参考:Pro TypeScript pages #40 #41

请注意:自本书编写以来,Microsoft 已将术语“内部模块”更改为“命名空间”:Namespaces

【讨论】:

  • 您能否添加一些代码,可能使用我的问题中的Observable 示例?
  • Module Augmentation 在这种情况下不起作用,因为您不能将接口上的函数声明为 static
  • @Dyna 很抱歉我没有足够的时间来创建和测试这样的代码。只需在我参考的书中学习“模块合并”的主题即可。它从第 40 页的末尾开始,非常简短且切中要害。因为您将有一个嵌套模块,所以可能有点棘手,但这是解决方案。
  • 阅读第 40/41 页后,Module Merging 部分我认为上述方法仅在使用 TS 中的内部模块时才有效。使用外部模块时,我无法创建module Observable {},因为这总是会导致错误“导入声明与'Observable'的本地声明冲突”
  • @Dyna 它可以正常工作,只有一件事:自从本书编写以来,微软已将“内部模块”的名称更改为“命名空间”。所以不要写“module Observable”,而是写“namespace Observable”。您无法再次创建此模块,但您可以使用此模块自动创建的相同命名空间:typescriptlang.org/docs/handbook/namespaces.html
猜你喜欢
  • 2021-11-15
  • 2016-12-02
  • 2018-05-25
  • 1970-01-01
  • 2015-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多