開発覚書はてな版

個人的な開発関連の備忘録

【TypeScript】拡張メソッドの実装(ライブラリ・外部モジュール編)

概要

TypeScriptで基本型でなく、他のライブラリで定義されているクラスに対して拡張メソッドを実装する方法を記載します。
declare module 'ライブラリの拡張対象のクラスが記載されているファイル'で定義後は基本型の拡張方法と同じです。
サンプルソースを記載しているので、そちらの方が分かりやすいと思います。

基本型(string, number, Array etc)の拡張は以下の記事を参照して下さい。

kakkoyakakko2.hatenablog.com

動作環境

  • Angular 6.0.0
  • TypeScript 2.7.x

サンプルソース

http.extension.ts
import { HttpClient, HttpErrorResponse, HttpResponse } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';

// ライブラリの拡張対象のクラスがあるファイルを指定する。
declare module '@angular/common/http/src/client' {

    // 拡張対象のクラスにメソッドを定義
    interface HttpClient {
        /**
         * POST拡張:戻り値がHTTPステータスコード
         * @param url  URL
         * @param body データ
         */
        postEx(url: string, body: any): Observable<number>;
    }
}

// 拡張メソッドを実装
HttpClient.prototype.postEx = function(url: string, body: any) {
    const client = this as HttpClient;
    return client.post(url, body, { observe: 'response' }).pipe(
        map((res: HttpResponse<any>) => {
            return res.status;
        }),
        catchError((err: HttpErrorResponse) => {
            return of(err.status);
        })
    );
};
呼び出し元のクラス
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

import './http.extension';

@Injectable()
export class AppService {

    constructor(private http: HttpClient) { }

    register(): Observable<number> {
        return this.http.postEx('api/data', null);
    }
}

その他

  • ライブラリのバージョンアップなどにより、拡張対象のクラスの配置が変わる場合があるので注意が必要です。
  • 元となるファイルに対して指定が必要です。AngularのHttpClientを拡張する場合、@angular/common/httpではなく、実際にクラスが定義されている@angular/common/http/src/clientを指定しないと上手く拡張できません。