🔥

Honoが返すJSONの型を明示したい!

2024/01/31に公開1

結論

ReturnType<typeof c.json<...>>

はじめに

Hono、便利ですよね。
しかし、Honoを使っていると、c.json()が返すJSONの型を明示したいときがあります。

export type Ok<T> = { ok: true; value: T };
export type Err<E = string> = { ok: false; error: E };

export type Result<T, E = string> = Ok<T> | Err<E>;

私は、このようなResult型をよく使います。Honoで返すJSONもこのResult型に沿うようにしています。

const app = new Hono().get("/", async (c) => {
  const res = await processPossibleFail();

  if (!res.success) {
    return c.json({ ok: false, error: res.error }, 500);
  }

  return c.json({ ok: true, value: res.value }, 200);
});

このような感じです。これはreturnが2箇所なのでまだいい方ですが、早期returnの数が増えてくると、すべてのreturnで期待した型になっているか不安になってきます。ひとつずつsatisfiesなどでチェックするのも面倒です。

そこで、ハンドラが返す型を明示的に指定したいと思いました。

const app = new Hono().get(
  "/",
  async (c): Promise<ReturnType<typeof c.json<Result<{ text: string }>>>> => {
    const res = await processPossibleFail();

    if (!res.success) {
      return c.json({ ok: false, error: res.error }, 500);
    }

    const text = res.value.text;

    return c.json({ ok: true, value: { text } }, 200);
  }
);

おわりに

調べても出てこなかったので記事にしたのですが、もしかしたらもっといい方法があるかもしれません。

ちなみに、毎回ReturnType<typeof c.json<...>>と書くのは面倒なので、

type HonoJSON<T> = ReturnType<Context['json']<T>>

という風にしたかったのですが、ダメみたいです。

GitHubで編集を提案

Discussion

airRnotairRnot

ちなみに、@hono/zod-openapiを使えばこんなこと気にする必要なくなります。