薪のイラスト

MSW v2 で `HttpResponse.json()` の型がおかしいときの対処法

MSW v2 の `HttpResponse.json()` の第 2 引数の型は `Response` オブジェクトの初期化時に渡すオプションを指定できます。しかし、tsconfig.json の設定によっては、この型がおかしくなることがあります。その場合には、`tsconfig.json` の `compilerOptions.lib` に `dom` を追加するのが一時的な対処法です。

TL;DR

tsconfig.jsoncompilerOptions.libdom を追加する。

{
  "compilerOptions": {
    "lib": ["dom"]
  }
}

また、[node] Expose global ResponseInit; remove NodeJS.fetch namespace by thw0rted · Pull Request #67341 · DefinitelyTyped/DefinitelyTyped で問題が修正される予定です。

MSW の HttpResponse クラス

MSW の v2 では、モックのレスポンスは Fetch API の Response オブジェクトを返すようになりました。Response オブジェクトを返すクラスとして HttpResponse が用意されていますので、普段のモックの実装はこれを使うことになります。

import { http, HttpResponse } from "msw";
 
const handler = http.post("/user", (req, res: HttpResponse) => {
  return HttpResponse.json(
    {
      name: "John",
      age: 32,
    },
    { status: 201 },
  );
});

この HttpResponse.json の第 2 引数には、Response オブジェクトの初期化時に渡すオプションを指定できます。このオプションには statusstatusTextheaders があります。

ResponseInit 型がおかしい問題

しかしながら、tsconfig.json の設定によっては、HttpResponse.json の第 2 引数の型がおかしくなることがあります。以下のように、{ type: any } 型としてサジェストされてしまっています。

なぜこのようなことが起きてしまっているのでしょうか?型定義を見てみましょう。HttpResponse.json の第 2 引数の型は HttpResponseInit となっています。

declare class HttpResponse extends Response {
    /**
     * Create a `Response` with a `Content-Type: "application/json"` body.
     * @example
     * HttpResponse.json({ firstName: 'John' })
     * HttpResponse.json({ error: 'Not Authorized' }, { status: 401 })
     */
    static json<BodyType extends JsonBodyType>(body?: BodyType | null, init?: HttpResponseInit): StrictResponse<BodyType>;

HttpResponseInitResponseInit を継承しています。

interface HttpResponseInit extends ResponseInit {
  type?: ResponseType;
}

この ResponseInitlib.dom.d.ts で定義されているため、もし tsconfig.json が Node.js アプリケーション向けに設定されていて compilerOptions.libdom が含まれていない場合、ResponseInit が見つからず正しい型情報が得られないということになります。

この問題を修正するには、tsconfig.jsoncompilerOptions.libdom を追加する必要があります。

{
  "compilerOptions": {
    "lib": ["dom"]
  }
}

この問題は Node.js に fetch API が提供されているのにも関わらず、@types/nodeResponseInit が定義されていないことに起因しています。この問題は [node] Expose global ResponseInit; remove NodeJS.fetch namespace by thw0rted · Pull Request #67341 · DefinitelyTyped/DefinitelyTyped がマージされることで解決される予定です。

参考


Contributors

> GitHub で修正を提案する
この記事をシェアする
はてなブックマークに追加

関連記事