☁️

Cloudflare WorkerのRPC Bindingをmonorepoかつ型付きでやるtips

に公開

皆さん、CloudflareでWorkerをService Bindingする時、こう思ったことはないですか?

wrangler typesで生成されたworker-configuration.d.tsにRPC Bindingの適切な型がねぇ、と。

env.HogeService.fetch()しか無い、定義した関数がintellisenseに出てこない。めんどい。私はずっとそう思っていました。

しかし7月29日にリリースされたwrangler@4.26.1にて、これが解決されました。やったぜ。

tl;dr

wranglerのglobal option, --configを使う[1]

wrangler types -c ./wrangler.jsonc -c ../hoge-service/wrangler.jsonc

生成される型定義ファイル

declare namespace Cloudflare {
	interface Env {
            HogeService: Service<typeof import("../hoge-service/src/index").default>
	}
}
interface Env extends Cloudflare.Env {}

これで、primary以降に指定したworker(wrangler.jsonc)を"型付きで"生成できる。

formatはこんな感じ

wrangler types -c <PrimaryWorker Config file path> [-c <RPC Worker Config file path>]...

🎉😀🎉

何故これが良いのか

👍 localで実行した時の警告文が出なくなる

❓ Your types might be out of date. Re-run `wrangler types` to ensure your types are correct.

👍 グローバルな型定義を維持出来る

例えば...

import type HogeServiceType from "@project/HogeService"

declare namespace Cloudflare {
	interface Env {
		HogeService: HogeServiceType
	}
}
interface Env extends Cloudflare.Env {}

このようなコードにしてしまうと...

  • module扱いになってしまい、全てのファイルでworker-configuration.d.tsをimportしなくてはいけなくなる

  • worker-configuration.d.tsでのambient 宣言(RpcTarget, WorkerEntrypoint)が参照不能になる

  • 従来の@cloudflare/worker-typesはworker以外のために公開されるようになったため、公式推奨構成では無くなってしまう

// 型エラー(型定義ファイルがmoduleになっているため参照不能)
import { RpcTarget, WorkerEntrypoint } from 'cloudflare:workers';

// module化しているためEnvの他にR1/D1/KV/Queueと言った型もimport必須
import type { Env } from '../worker-configuration.d.ts';

export default class extends WorkerEntrypoint<Env> {
	async fetch(): Promise<Response> {
		return new Response('Hello World!');
	}

	async add(a: number, b: number) {
		return a + b;
	}
}

といった余りにも重い制約が課されてしまいます。コレジャナイ感すごい。

まとめ

wranglerのversionをbumpしよう。

補足(従来のやり方)

versionup出来ない等の事情があっても、表題の要件は達成できます。

  1. @cloudflare/workers-typesをinstallする

  2. tsconfigのcompilerOptions.typesに@cloudflare/workers-typesを含める

{
	"compilerOptions": {
		"types": ["@cloudflare/workers-types"],
	},
}

  1. typed importをする
import type HogeServiceType from '@project/hoge-service';

interface Env {
	HogeService: Service<HogeServiceType>
}

  • worker-configuration.d.tsがmoduleになるためimportしなくてはいけない
  • wrangler typesを実行してはいけない

このような制約は変わりません。

補足2

turborepoやhono等で型チェックが通らなくなる(場合がある?)、らしいです。issue comment

その場合は補足の方法でなんとかなりそうです。多分。

でももっと他に良い方法もあるかも。たぶん。

脚注
  1. https://developers.cloudflare.com/workers/wrangler/commands/#types ↩︎

GitHubで編集を提案

Discussion