TypeSpec specialist
TypeSpec を「信頼できる情報源(Single Source of Truth)」として位置付け、堅牢で保守性の高い API スキーマを設計・検証する専門スキル。
責務(Scope)
このスキルは以下の 4 つのモードで動作する。冒頭でユーザーの依頼内容からモードを判定し、必要であれば推奨案を含む複数の選択肢を提示してユーザーに確認する。
モード判定のヒント: ユーザー発話に以下のキーワードが含まれていれば対応モードを優先候補とする。複数該当・あいまいな場合のみ推奨案を含む複数の選択肢を提示してユーザーに確認する。
| キーワード例 | モード | |---|---| | 新規 / 設計して / 実装して / ゼロから / 一から | Mode 1: 新規実装 | | レビュー / 検証 / チェック / 監査 / 改善点 | Mode 2: レビュー・検証 | | 移行 / 変換 / OpenAPI から / Swagger から / JSON Schema から | Mode 3: 移行 | | セットアップ / 初期化 / プロジェクト立ち上げ / tspconfig / package.json | Mode 4: セットアップ |
- 新規実装モード: 要件から
.tspファイル群を新規設計・実装する - レビュー・検証モード: 既存
.tsp実装を best-practices に照らして検証し、改善提案をレポートする - 移行モード: OpenAPI / JSON Schema を TypeSpec に変換・移行する
- セットアップモード: TypeSpec プロジェクトの初期構成(
tspconfig.yaml,package.json, ディレクトリ構造等)を整備する
必須リファレンス
作業開始前に必ず references/best-practices.md を読み込むこと。 TypeSpec 1.13.0 時点の最新ベストプラクティスが記載されており、本スキルの判断基準はすべてこの文書に準拠する。
参照すべきリファレンス:
| ファイル | 主な用途 |
|---|---|
| references/best-practices.md | 全モードで必読の中核ガイド(11 章構成) |
| references/versioning-guide.md | バージョニングを扱う際の詳細ガイド |
| references/migration-openapi.md | 移行モードで参照する実践ガイド |
| references/tspconfig-cookbook.md | セットアップモード・CI 連携で参照するレシピ集 |
best-practices.md の章立て:
| 章 | テーマ |
|----|--------|
| 1 | 名前空間のネスト |
| 2 | 共通パラメータの再利用 |
| 3 | カスタムレスポンス・エラーモデル |
| 4 | Visibility の活用 |
| 5 | ルーティング |
| 6 | バージョニング(詳細は versioning-guide.md) |
| 7 | 認証・認可 |
| 8 | 命名規則・ドキュメント |
| 9 | プロジェクト構造 |
| 10 | Linter(詳細は tspconfig-cookbook.md) |
| 11 | 下流ツールチェーン統合(移行は migration-openapi.md) |
共通の作業原則
バージョン認識
TypeSpec は 2025 年 5 月に 1.0 GA。コア・主要拡張は 1.x 系で安定運用中(執筆時点の最新は 1.13.0。実バージョンは npm view @typespec/compiler version 等で確認すること)。以下の点に特に注意:
@serviceの構文は object value literal#{ ... }が正規(1.0 以降)。旧来の({ ... })は非推奨@patchは暗黙的な省略可能化を行わない(1.0 以降)。部分更新には@typespec/httpのMergePatchUpdate<T>を使う。upsert にはMergePatchCreateOrUpdate<T>を使う@patch(#{ implicitOptionality: true })は非推奨(1.12.0 で正式に deprecated)。明示的な patch モデルかMergePatchUpdate<T>に移行する@withVisibilityFilterは非推奨(1.11.0 以降)。FilterVisibilityテンプレートを使うinternal修飾子は安定化済み(1.13.0 以降)。#suppress "experimental-feature"は不要@tagMetadataは配列形式とsummary/kindフィールドに対応(1.13.0 以降)@typespec/versioning/@typespec/rest/@typespec/xmlなどはプレビュー(番号体系は 0.x)。本番採用時は変更リスクを明示する- パッケージ番号体系の混在に注意: コア・
@typespec/http・@typespec/openapi(3)・@typespec/json-schemaは 1.x stable、@typespec/restおよび各種プレビュー拡張は 0.x。package.jsonを書く際はnpm view <pkg> versionで実バージョンを確認する
出力フォーマット
.tspコード例は実行可能な完全な形で提示する(必要なインポート文を含む)- レビュー結果は表形式または箇条書きで構造化する
- ファイル分割を提案する場合はディレクトリツリーを示す
モード別ワークフロー
Mode 1: 新規実装モード
ユーザーが API 要件から .tsp ファイルを新規作成したい場合。
手順:
-
要件ヒアリング(推奨案を含む複数の選択肢の提示を活用)
- 対象ドメイン(リソース、操作)
- 認証方式(Bearer / OAuth2 / なし)
- バージョニング要否
- エミッター対象(OpenAPI 3.0 / 3.1 / JSON Schema)
- クライアント・サーバーコード生成の要否
-
プロジェクト構造の決定
- 規模が小さい場合(< 5 リソース):
main.tsp一枚で開始してよい - 規模が大きい場合: best-practices.md「9. プロジェクト構造」のディレクトリ構成を採用
main.tsp models/ common.tsp # エラー型・ページネーション・ResponseWrapper 等 <resource>.tsp routes/ <resource>.tsp
- 規模が小さい場合(< 5 リソース):
-
モデル設計
- 命名規則: モデル/Namespace/Interface =
PascalCase、操作/プロパティ =camelCase - 自動採番 ID は
@visibility(Lifecycle.Read)で読み取り専用に - パスワード等の機密入力は
@visibility(Lifecycle.Create)で書き込み専用に - 検索フィルタは
@visibility(Lifecycle.Query)でクエリ専用に - 部分更新が必要な場合は
MergePatchUpdate<T>を使用(要import "@typespec/http") - すべてのモデル・操作に
/** */または@docでドキュメントコメントを付与
- 命名規則: モデル/Namespace/Interface =
-
エラー設計
@errorデコレータでValidationError/NotFoundError/ConflictError等を定義- 共通レスポンスラッパーを使う場合はジェネリック
Response<T>パターンを採用 - 操作の戻り値は
OkResponse | ValidationError | NotFoundErrorのように union で列挙
-
認証定義
- Namespace 全体に
@useAuth(BearerAuth)等を適用 - 認証不要のエンドポイントは個別に
@useAuth(NoAuth)で上書き
- Namespace 全体に
-
tspconfig.yaml の生成
- エミッター指定(
@typespec/openapi3等) - Linter 設定(新規プロジェクトなら
@typespec/http/all、既存組み込みならrecommended) - 出力先パスの明示
- 詳細は
references/tspconfig-cookbook.mdを参照
- エミッター指定(
-
完成物の提示
- ディレクトリツリー
- 各ファイルの内容
tsp compileの想定実行コマンド- 期待される OpenAPI 出力の概要
Mode 2: レビュー・検証モード
既存の .tsp ファイル群を best-practices に照らして検証する場合。
手順:
-
対象の特定
- レビュー対象ファイルパスを確認(複数の場合は全て)
- レビューの観点(全章 / 特定章のみ / セキュリティ / パフォーマンス)を確認
-
構造化チェック 各ファイルを読み込み、以下のチェックリストで検証する:
| カテゴリ | チェック項目 | |----------|--------------| | 名前空間 | 論理的にネスト化されているか /
operationIdの衝突がないか | | 共通化 | リクエスト ID 等がモデル化されスプレッドされているか / ハードコードされていないか | | レスポンス | カスタムレスポンス/エラーが定義されているか / 戻り値に union でエラーが含まれているか | | Visibility | ID は Read 専用か /@withVisibilityFilterを使っていないか(→FilterVisibilityへ) | | ルーティング |@routeと@autoRouteの使い分けが一貫しているか | | Versioning | バージョン管理が必要なら@versionedが設定されているか | | 認証 |@useAuthがすべての保護対象に明示されているか | | 命名 | PascalCase / camelCase が遵守されているか | | ドキュメント | すべての公開モデル・操作に doc コメントがあるか | | プロジェクト構造 | 規模に対して適切に分割されているか | | tspconfig | Linter が CI で動くよう設定されているか /kind: projectの活用を検討 | | バージョン互換性 |@serviceの#{}構文 /@patchのMergePatchUpdate<T>使用 /@patch(#{ implicitOptionality: true })不使用 | | タグメタデータ |@tagMetadata配列形式と名前指定形式が混在していないか | | 非推奨構文 |@withVisibilityFilter/@patch(#{ implicitOptionality: true })/#suppress "experimental-feature"oninternalを使っていないか | | パッケージバージョン |package.jsonのバージョンが実 npm と整合しているか | -
レポート出力
以下のテンプレートで出力する:
# TypeSpec レビューレポート ## サマリ - 対象ファイル: <ファイル一覧> - 検出された問題: <件数>(致命的: N / 警告: M / 提案: L) ## 致命的(Critical) <コンパイルエラーや誤った API 契約に繋がる問題> ## 警告(Warning) <best-practices に明確に違反している問題> ## 提案(Suggestion) <改善余地のある設計> ## 良い点 <既に best-practices に従えている部分>各指摘には以下を含めること:
- 該当ファイル:行番号
- 問題の概要
- best-practices.md の該当章
- 修正前 → 修正後のコード例
- 修正の根拠(なぜそうすべきか)
Mode 3: 移行モード(OpenAPI/JSON Schema → TypeSpec)
既存の OpenAPI 仕様や JSON Schema を TypeSpec に変換する場合。
この作業は references/migration-openapi.md に詳細手順が記載されている。 必ずこのファイルを参照しながら進める。
要点のみ:
- 元ファイル形式(OpenAPI 3.0 / 3.1 / Swagger 2.0 / JSON Schema draft)を判定
- 自動変換ツールの利用可否を検討(規模が大きい場合は叩き台として有効)
- マッピング表に従って構造を変換
- 単純変換に留めず、移行を機に共通化・Visibility 導入・エラー統一などの再設計を実施
- 移行後の
tsp compileによるOpenAPI再生成と元仕様との差分確認は、変換対象が大きい(多数のモデル・ルートを含む)場合はサブエージェントに委譲し、メインには差分の要点(欠落・型不一致等)だけを戻させる。小規模な変換(数モデル程度)であれば、委譲せずメインで直接実行してよい
Mode 4: セットアップモード
新規 TypeSpec プロジェクトを立ち上げる場合。
手順:
-
環境前提の確認
- Node.js のバージョン(v20 以上推奨)
- パッケージマネージャ(npm / pnpm / yarn)
-
package.json の準備
バージョンは
npm view <pkg> versionで実バージョンを確認した上で記述する。番号体系がパッケージごとに異なる点に注意:{ "devDependencies": { "@typespec/compiler": "^1.13.0", "@typespec/http": "^1.13.0", "@typespec/openapi": "^1.13.0", "@typespec/openapi3": "^1.13.0" }, "scripts": { "build": "tsp compile .", "watch": "tsp compile . --watch", "format": "tsp format \"**/*.tsp\"", "format:check": "tsp format --check \"**/*.tsp\"" } }オプション(必要に応じて追加):
@typespec/json-schema(^1.x): JSON Schema 出力@typespec/versioning(^0.x、プレビュー): バージョニング@typespec/rest(^0.x、プレビュー扱い、リソース指向ルーティング)
プレビューパッケージを使う場合は将来の API 変更リスクをユーザーに明示する。
-
tspconfig.yaml の作成
1.13.0 以降は
kind: projectとentrypointでプロジェクト境界とエントリポイントを明示できる:kind: project entrypoint: main.tsp emit: - "@typespec/openapi3" options: "@typespec/openapi3": emitter-output-dir: "{output-dir}/schema" openapi-versions: - 3.1.0 linter: extends: - "@typespec/http/all"kind/entrypointは省略可能(従来互換)。モノレポや複雑なプロジェクト構成で境界を明示したい場合に有効。既存プロジェクトに後付けする場合は
@typespec/http/recommendedから始めるのが現実的。詳細はreferences/tspconfig-cookbook.mdを参照。 -
ディレクトリ構造の生成 規模に応じて
main.tsp一枚 ormodels/+routes/の分割を選択(best-practices.md 章 9)。 -
CI 連携の提案
tsp format --checkをプリコミットフック・CI に追加tsp compile . --warn-as-errorで Linter 警告も CI 失敗扱いにtsp compile . --statsで複雑度監視(1.1.0 以降)- 生成された OpenAPI を artifact として保存
-
VS Code 拡張の案内 ユーザーが VS Code を使っているなら「TypeSpec for VS Code」拡張のインストールを推奨。
実装サンプル(クイックリファレンス)
完全なコード例は references/best-practices.md を参照。以下は典型パターンの抜粋。
サービス定義(@service の正規構文)
import "@typespec/http";
using TypeSpec.Http;
@service(#{ title: "My API" })
@server("https://api.example.com", "Production endpoint")
namespace MyApi;
共通レスポンスラッパー
namespace DefaultResponse;
model Response<T> {
@statusCode statusCode: int32;
data: T;
error: ResponseError;
}
model ResponseError {
message: string;
code?: string;
}
Visibility を使ったモデル定義
model TodoItem {
@visibility(Lifecycle.Read)
id: string;
content: string;
@visibility(Lifecycle.Create)
initialTag?: string;
@visibility(Lifecycle.Read, Lifecycle.Update)
lastModifiedAt?: utcDateTime;
}
// クエリパラメータ専用
model TodoQueryParams {
@query
@visibility(Lifecycle.Query)
status?: "open" | "done";
}
FilterVisibility(1.11.0 推奨)
model CreateAndReadExample is FilterVisibility<
Example,
#{ all: #[Lifecycle.Create, Lifecycle.Read] },
"CreateAndRead{name}"
>;
部分更新(MergePatchUpdate / MergePatchCreateOrUpdate)
import "@typespec/http";
using TypeSpec.Http;
// 部分更新(PATCH)
@patch op update(@body pet: MergePatchUpdate<Pet>): void;
// 作成または更新(upsert)
@patch op createOrUpdate(@body pet: MergePatchCreateOrUpdate<Pet>): void;
@tagMetadata の配列形式(1.13.0 以降)
@service(#{ title: "Pet Store" })
@tagMetadata(#[
#{ name: "Pets", description: "Pet management operations" },
#{ name: "Orders", description: "Order management", summary: "All order operations", kind: "OrderGroup" },
])
namespace PetStore;
配列形式は OpenAPI ドキュメント上のタグ出現順序を明示的に制御できる。summary と kind は OpenAPI 3.2 ではネイティブフィールド、3.0/3.1 では x-oai-summary/x-oai-kind 拡張として出力される。
認証付きインターフェース
@useAuth(BearerAuth)
interface ProtectedRoutes {
@get getProfile(): UserProfile;
@useAuth(NoAuth)
@get getPublicInfo(): PublicInfo;
}
アンチパターン警告
以下を検出したら必ず指摘する:
@service({ title: "..." })(1.0 以降は object value literal@service(#{ title: "..." }))@patch op update(@body pet: Pet)(1.0 以降はMergePatchUpdate<Pet>を使用)@patch(#{ implicitOptionality: true })(1.12.0 で正式に deprecated。明示的な patch モデルかMergePatchUpdate<T>に移行)@withVisibilityFilter(1.11.0 以降はFilterVisibilityテンプレート)@defaultResponseを@statusCode付きモデルや@errorモデルに適用(1.13.0 で警告対象)@tagMetadata("name", #{...})と@tagMetadata(#[...])の混在(1.13.0 で診断エラー)#suppress "experimental-feature"をinternal修飾子に使用(1.13.0 で不要に)- ID プロパティに Visibility 指定なし(
Lifecycle.Readを推奨) - 共通パラメータが各操作にハードコード(モデル化+スプレッド推奨)
- エラーが生のステータスコード返却のみ(
@errorモデル化推奨) - 名前空間なしのフラット構造(規模に応じてネスト化)
- ドキュメントコメントなしの公開モデル
- Linter 未設定の
tspconfig.yaml package.jsonの TypeSpec パッケージバージョンが実 npm と乖離(特に@typespec/httpを^1.xと書く誤り)- 各 op に同一
@tagを繰り返し付与(interface に 1 回付ければ伝搬する) - 同一ファイルの重複インポートや自己インポート(1.12.0 で警告対象)
完了時のチェックリスト
作業完了時は以下を必ず報告する:
- [ ] 何を変更/作成したか(ファイル一覧)
- [ ] best-practices.md のどの章に従ったか
- [ ]
tsp compileが成功する想定か(実環境で検証可能なら実行を促す) - [ ] プレビュー機能を使った場合の将来リスク
- [ ] 次のステップ(コード生成・CI 連携など)