mcpField
Q
quality-code

quality-code

github.com/rhyssullivan開発104235 回インストール16 週間前に更新
リポジトリ

quality-code について

フルスタック TypeScript の開発者向けに、コード作成とレビューの指針を示すスキルです。型による状態の制約、エンドツーエンドの型連携、実サービスを使ったテスト、OpenTelemetry に重点を置きます。

主な機能

  1. 01ブランド型と判別可能なユニオンで状態を制約
  2. 02型をエンドツーエンドで共有・導出
  3. 03オブジェクト引数を優先
  4. 04Standard Schema による検証
  5. 05実サービスを使ったテスト
  6. 06OpenTelemetry による計装

活用シーン

  1. 01無効状態の少ない API の設計
  2. 02クライアントとサーバーの型重複を削減
  3. 03再利用可能な検証スキーマの受け入れ
  4. 04データベースやローカルクラウドサービスの動作をテスト

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/rhyssullivan/skills --skill quality-code

インストール後、Claude Code で/quality-codeを入力して読み込まれたか確認します。

詳細

高品質なフルスタック TypeScript を記述する

TypeScript コードを記述またはレビューするときは、以下の原則を適用してください。

表現できない状態を作る

型システムを使って、無効な状態がコンパイル時にエラーになるようにします。到達可能な状態が少ないほど、コードの読み取りや変更が容易になります。

ブランド型

プリミティブ型にブランドを付け、取り違えを防ぎます。境界で一度検証すれば、その後のコードでは型を信頼できます。

type PhoneNumber = string & { __brand: "PhoneNumber" };

function parsePhone(input: string): PhoneNumber {
  if (!/^\+?\d{10,15}$/.test(input)) throw new Error(`Invalid: ${input}`);
  return input as PhoneNumber;
}

function sendSMS(to: PhoneNumber, body: string) {
  /* input is trusted */
}

プロジェクトですでにネイティブのブランド型をサポートするライブラリ(Effect など)を使用している場合は、独自に実装するのではなく、そのライブラリのプリミティブを使ってください。

フラグの集合より判別可能なユニオン
// Don't — invalid combos representable
type State = { loading: boolean; user?: User; error?: string };

// Do — only valid states exist
type State =
  | { status: "loading" }
  | { status: "success"; user: User }
  | { status: "error"; error: string };

型をエンドツーエンドで引き継ぐ

DB スキーマ → サーバー → クライアント間で、手動で重複させることなく型を共有します。プロジェクトですでに採用しているエンドツーエンドの型ツール(tRPC、oRPC、Elysia、TanStack Start)を使ってください。users.email が Email としてブランド付けされていれば、クライアントにもブランド付きのまま届くようにします。

導出できる型を再記述しないでください。新しいインターフェースを書く前に、Pick、Omit、Parameters、ReturnType、Awaited、typeof などを使います。関数の引数は手作業で型を付けるのではなく、定義元から推論してください。

// Don't — duplicate shape, drifts when the row changes
type UserSummary = { id: string; email: Email };
function renderUser(u: UserSummary) {
  /* ... */
}

// Do — derive from the source of truth
type User = Awaited<ReturnType<typeof db.query.users.findFirst>>;
function renderUser(u: Pick<User, "id" | "email">) {
  /* ... */
}

位置引数ではなくオブジェクトを渡す

// Don't — swap two args, still compiles
sendEmail("Welcome!", "Hi there");
// Do — order-independent, self-documenting
sendEmail({ to: "[email protected]", body: "Hi there" });

パフォーマンスが特に重要なホットパスでは避け、それ以外ではデフォルトで使ってください。

共有バリデーションには Standard Schema を使う

バリデーターを選びたくないライブラリやコードでは、StandardSchemaV1<unknown, T> を受け取るようにしてください。

できる限り実環境に近いテストを行う

実行できるものはモックせず、実際のサービスを起動してください。

  • AWS には LocalStack
  • Cloudflare Workers には Miniflare
  • モック DB ではなく、実際の Postgres/SQLite(例:bun:sqlite)

テスト環境のないサードパーティサービスだけをモックしてください。

print ログではなく OpenTelemetry を使う

オブザーバビリティを追加するときは、OTel スパンを使って計装してください。ユーザーからリクエスト ID が送られてきたときに、推測ではなく回答できるようになることを考えれば、初期設定のコストはすぐに回収できます。

コメント