在TypeScript中以类型安全的方式用静态函数从外部库扩展一个类

Extend a class from an external library with a static function in a typesafe manner in TypeScript

本文关键字:扩展 一个 从外部 TypeScript 类型安全 静态函数 方式用      更新时间:2023-09-26

我想用static函数扩展rxjs5 Observable类。我可以在纯JavaScript中实现:

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

这个工作,但在TypeScript我不能访问Observable.myStaticFn的属性myStaticFn是未知的类Observable

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

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

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上放置不同的静态方法,这个概念也会失败,这取决于导入的模块。

我在查看RxJS源代码中静态.from()扩展的实现时发现了这一点:

import { myStaticFn as myStaticFnStatic } from "./myStaticFn";
declare module "rxjs/Observable" {
    namespace Observable {
        let myStaticFn: myStaticFnStatic;
    }
}

请注意我是如何导入myStaticFn的,但它在本地的范围为myStaticFnStatic -这是必需的,否则你会得到一个编译器错误。

在rx的定义文件中有Observable类和ObservableStatic的定义。
如果你想添加静态函数,那么你需要增加ObservableStatic:

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

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

参考:Pro TypeScript pages #40 #41

只有一个注意事项:自本书撰写以来,微软已将术语"内部模块"更改为"命名空间":