mcpField
T
type-coverage

type-coverage

github.com/marius-townhouseテスト・品質643 回インストール38 週間前に更新
リポジトリ

type-coverage について

具体的な型を持つシンボルと any のシンボルの割合を測定し、経時的に追跡する TypeScript スキルです。JavaScript の移行や型安全性の維持に取り組むチームが、基準値を設けて CI での低下を検出できます。

主な機能

  1. 01型付きシンボルのカバレッジ測定
  2. 02any 型のシンボルの特定
  3. 03最低カバレッジ基準の設定
  4. 04変化の追跡と低下の防止

活用シーン

  1. 01JavaScript 移行中の型安全性の監視
  2. 02コードレビューでのカバレッジ確認
  3. 03基準を下回った場合の CI 失敗
  4. 04any 型の解消作業の優先順位付け

インストール

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

$npx skills add https://github.com/marius-townhouse/effective-typescript-skills --skill type-coverage

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

詳細

型安全性の後退を防ぐために型カバレッジを追跡する

概要

コードのうち、型が付いている部分と any になっている部分の割合を監視します。

型カバレッジは、実際の型が付いているシンボルと any になっているシンボルの割合を測定します。型安全性の後退を防ぐため、時間の経過に伴う変化を追跡しましょう。

このスキルを使う場面

  • JavaScript から TypeScript への移行
  • 型の品質を長期にわたって維持する場合
  • 型安全性に関するコードレビュー
  • any の削減状況を測定する場合

鉄則

What gets measured gets managed.
Track type coverage; set coverage goals.

覚えておきましょう:

  • any は気づかないうちにコード全体へ広がります
  • カバレッジは気づかないうちに低下することがあります
  • 明示的に追跡することで、品質の低下を防げます
  • カバレッジ向上に向けたチーム目標を設定しましょう

型カバレッジを理解する

let x: number = 1;        // x is covered (has real type)
let y: any = 2;           // y is NOT covered (has any)
let z = JSON.parse('{}'); // z is NOT covered (implicit any from JSON.parse)

型カバレッジ = (カバーされているシンボル数) / (シンボルの総数)

カバレッジを測定するツール

type-coverage パッケージ
npm install -g type-coverage
type-coverage --detail

出力:

23384/24058 97.20%

--detail を指定すると、any になっているシンボルが表示されます:

src/api.ts:15:7 - data
src/utils.ts:42:3 - result
プロジェクト固有の設定
// package.json
{
  "scripts": {
    "type-coverage": "type-coverage --at-least 95"
  }
}

カバレッジがしきい値を下回った場合に CI を失敗させます。

any の発生源

1. 明示的な any
function process(data: any) { ... }  // Developer wrote any
2. 暗黙的な any(noImplicitAny がオフの場合)
function process(data) { ... }  // data is implicitly any
3. ライブラリに由来する any
const data = JSON.parse(str);   // Returns any
const result = $.ajax(url);     // jQuery returns any
4. 連鎖する any
function getUser(): any { ... }
const user = getUser();
//    ^? any - spreads from function

const name = user.name;
//    ^? any - continues spreading

改善のための戦略

JSON.parse を置き換える
// Before: returns any
const data = JSON.parse(str);

// After: validate with zod
const schema = z.object({ name: z.string() });
const data = schema.parse(JSON.parse(str));
//    ^? { name: string }
ライブラリの型を修正する
// Augment JSON.parse to return unknown
declare global {
  interface JSON {
    parse(text: string): unknown;
  }
}
代わりに unknown を使う
// Before
function parse(): any { ... }

// After
function parse(): unknown { ... }
型注釈を追加する
// Before: inferred as any from library
const result = externalLib.process(data);

// After: explicitly typed
const result: ProcessedData = externalLib.process(data);

経時的な追跡

# Record in CI
echo "$(date): $(type-coverage)" >> coverage-history.txt

# Fail if coverage decreased
type-coverage --at-least $(cat .type-coverage-baseline)

チーム目標の設定

マイルストーンカバレッジ目標
移行開始時50%
フェーズ 175%
フェーズ 290%
安定時95%+

コードベースの成熟に合わせて目標を引き上げましょう。

後退を防ぐ

コミット前フック
# .husky/pre-commit
type-coverage --at-least 95
CI チェック
# .github/workflows/ci.yml
- name: Type Coverage
  run: npx type-coverage --at-least 95
コードレビューのチェックリスト
  • 正当な理由のない新しい any 型がない
  • 型カバレッジが低下していない
  • 外部データが検証されている

必要な any への対処

any が避けられないこともあります:

// Document why any is needed
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const legacy: any = oldSystem.getData();  // TODO: Type when migrating legacy system

コメントやチケットでこれらを追跡しましょう。

実例

// Before migration: 60% coverage
// Sources of any:
// - JSON.parse: 15%
// - Legacy API: 12%
// - Untyped dependencies: 8%
// - Explicit any: 5%

// Action plan:
// 1. Add zod validation: +10%
// 2. Type legacy API responses: +10%
// 3. Add @types packages: +8%
// 4. Remove explicit any: +5%

// After: 93% coverage

プレッシャー耐性プロトコル

1. 「100% は達成できません」

プレッシャー:「型を付けられないコードもあります」

回答: 完璧さではなく、改善を目指しましょう。追跡できるものを追跡します。

対応: 現実的な目標を設定し、必要な例外を記録します。

2. 「作業量が多すぎます」

プレッシャー:「すべての any 型を修正するには時間がかかりすぎます」

回答: 段階的に改善しましょう。まず新しい any 型を防ぎます。

対応: 段階的に基準を引き上げ、新しい any を防ぎながら、既存のものを時間をかけて修正します。

危険信号 — 作業を止めて再検討する

  • カバレッジが時間の経過とともに低下している
  • 正当な理由のない新しい any 型がある
  • 関数の戻り値から any が広がっている
  • any を多用した未テストのコードがある

よくある正当化(すべて不適切)

言い訳実態
「any は 1 つだけです」any は広がり、1 つが多数になります
「あとで修正します」追跡しなければ、あとで修正されることはありません
「カバレッジは十分高いです」改善に合わせて、より高い目標を設定しましょう

クイックリファレンス

# Measure coverage
npx type-coverage

# With details
npx type-coverage --detail

# Fail if below threshold
npx type-coverage --at-least 95

# In package.json
"scripts": {
  "type-coverage": "type-coverage --at-least 95"
}

要点

後退を防ぐため、型カバレッジを追跡しましょう。

any 型は気づかないうちに広がります。測定しなければ、型安全性は時間とともに損なわれます。ツールでカバレッジを追跡し、目標を設定し、カバレッジが低下した場合はビルドを失敗させましょう。

参考文献

Dan Vanderkam 著『Effective TypeScript』、項目 49「型安全性の後退を防ぐために型カバレッジを追跡する」に基づいています。

コメント