ウェブエンジニア問題集
第11章

FastifyのTypeScriptとディレクトリ構成 — 実務で育てやすい形にする

4
この章の目次開く

ここまでの例はJavaScriptで進めました。Fastifyの概念をつかむにはJavaScriptで十分ですが、実務ではTypeScriptで書くことが多いです。この章では、いきなり高度な型テクニックへ行かず、まず育てやすい構成を整理します。

まず分ける責務

Fastifyアプリでは、次の4つを混ぜすぎないことが大切です。

役割
appFastifyインスタンス作成、plugin登録、共通エラー設定
routesHTTPの入口。request/reply、schema、status code
services業務ロジック。Todoを作る、完了にするなど
repositoriesDBアクセス。SQLやORMの詳細
src/
├── app.ts
├── server.ts
├── routes/
│   └── todos.ts
├── services/
│   └── todoService.ts
└── repositories/
    └── todoRepository.ts
FastifyのhandlerはHTTPの入口に留め、業務判断はserviceへ逃がすと、テストしやすく変更にも強くなります。

TypeScript化の最小セット

TypeScriptで始めるなら、まず必要なパッケージを入れます。

npm install fastify
npm install -D typescript @types/node tsx
bash

package.json のscriptsは、学習中なら tsx を使うと簡単です。

{
  "type": "module",
  "scripts": {
    "dev": "tsx watch src/server.ts",
    "start": "tsx src/server.ts",
    "test": "node --test --import tsx"
  }
}
json

tsconfig.json はまず標準的な設定で始めます。

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  }
}
json

requestの型を付ける

Fastifyでは、ルートごとに BodyParamsQuerystring などの型を指定できます。

type CreateTodoBody = {
  title: string;
};
 
fastify.post<{ Body: CreateTodoBody }>('/todos', async (request, reply) => {
  const title = request.body.title;
  return reply.code(201).send({ title, completed: false });
});
ts

構文: fastify.METHOD<RouteGeneric>(path, options, handler)

型パラメータ説明
Bodyrequest.body の型
Paramsrequest.params の型
Querystringrequest.query の型
Reply返すレスポンスの型

戻り値: ルート登録の結果としてFastifyインスタンスを返します。

schemaと型の二重管理

TypeScriptでFastifyを書くと、JSON SchemaとTypeScript型を両方書く場面があります。

type CreateTodoBody = {
  title: string;
};
 
const createTodoBodySchema = {
  type: 'object',
  required: ['title'],
  additionalProperties: false,
  properties: {
    title: { type: 'string', minLength: 1, maxLength: 100 },
  },
} as const;
ts

小さいうちはこの形で十分です。規模が大きくなったら、TypeBoxやZodなど、型と実行時schemaの重複を減らす選択肢も検討します。ただし、最初から道具を増やしすぎるより、Fastify標準のschemaを理解してから導入した方が判断しやすいです。

学習者学習者

TypeScriptを使えばschemaは不要になりますか?

先生先生

不要にはなりません。TypeScriptは書く人を助ける仕組みで、APIに来たJSONを実行時に止めるのはschemaの役割です。

参考リンク

次章では、ログ、CORS、環境変数、終了処理など、本番運用前に確認するポイントをまとめます。

Node.jsクイズに挑戦するTypeScript化の土台になるNode.jsとnpmの知識をクイズで確認しよう