mcpField
L
limit-any-type

limit-any-type

github.com/marius-townhouse開発648 回インストール39 週間前に更新
リポジトリ

limit-any-type について

根拠のない `any` の使用を避け、`unknown` や用途を絞った型などの代替策を解説する TypeScript スキルです。型の追加、JavaScript からの移行、ライブラリや API の値の扱いに役立ちます。

主な機能

  1. 01`any` のリスクの説明
  2. 02不明な値に `unknown` を提案
  3. 03用途に絞ったインターフェースと型エイリアス
  4. 04型チェックを回避する典型例の指摘
  5. 05API データの型設計の案内

活用シーン

  1. 01エラー回避目的の `any` の置き換え
  2. 02JavaScript 移行時の型追加
  3. 03API やライブラリ由来データの型定義

インストール

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

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

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

詳細

any 型の使用を制限する

概要

any 型を使うと、そのコードに対する TypeScript の型チェッカーが実質的に無効になります。

any は最後の手段として役立つこともありますが、型安全性、開発者エクスペリエンス、リファクタリングへの安心感、バグの防止といった TypeScript の利点を失わせます。

このスキルを使う場面

  • 型エラーを黙らせるために any を使おうとしている
  • JavaScript コードを TypeScript に移行している
  • 型定義のないサードパーティライブラリを扱っている
  • 複雑な型エラーに悩まされている
  • 既存のコードに型注釈を追加している

絶対に守るルール

NEVER use any without a specific, documented reason.

例外はありません:

  • 「とりあえずの応急処置だから」
  • 「型が複雑すぎるから」
  • 「あとで直すから」
  • 「実行時には動くから」

検出:「any の臭い」

any を書こうとしているなら、いったん手を止めて「もっとよい方法はないだろうか?」と考えてください。

// ❌ VIOLATION: Using any because it's "easy"
function processData(data: any) {
  return data.items.map((item: any) => item.name);
}

// ✅ CORRECT: Define proper types
interface DataItem {
  name: string;
}
interface Data {
  items: DataItem[];
}
function processData(data: Data) {
  return data.items.map(item => item.name);
}

any の5つの危険性

1. 型安全性がない
let age: number;
age = '12' as any;  // No error, but wrong!
age += 1;           // "121" at runtime
2. 契約を破る
function calculateAge(birthDate: Date): number { /* ... */ }

let birthDate: any = '1990-01-19';  // string, not Date!
calculateAge(birthDate);  // No error, but will fail
3. 言語サービスが使えない
// With proper types: autocomplete, refactoring, documentation
person.  // Shows: name, age, email...

// With any: nothing
(person as any).  // No autocomplete
4. リファクタリングのバグを見逃す
interface Props {
  onSelectItem: (id: number) => void;  // Changed from (item: any)
}

function handleSelectItem(item: any) {
  selectedId = item.id;  // Bug! Should be just `item` now
}
5. 型設計の問題を隠す
// ❌ BAD: What is this state?
const appState: any = { /* ... */ };

// ✅ GOOD: Clear, documented design
interface AppState {
  user: User | null;
  preferences: UserPreferences;
  isLoading: boolean;
}

プレッシャーへの対処法

1. 「複雑すぎる」

プレッシャー:「型が複雑すぎる。any のほうが簡単だ」

**対応:**複雑な型は、複雑なデータを表していることがよくあります。型を定義すれば、データモデルを理解し、文書化することにつながります。

**行動:**型を分解してください。インターフェースと型エイリアスを使いましょう。「このデータは実際にはどのような形をしているのか?」と問いかけてください。

2. 「あとで直す」

プレッシャー:「戻ってきたときに適切な型を追加する」

**対応:**おそらく実行しません。技術的負債は蓄積し、any はコードベース全体に広がります。

**行動:**今すぐ直してください。本当に直せない場合は、チケット番号を付けた // TODO を追加してください。

3. 「ライブラリに型定義がない」

プレッシャー:「この npm パッケージには @types がない」

**対応:**いくつか方法があります。最小限の型定義を書く、unknown を使う、または .d.ts ファイルを作成する方法です。

**行動:**自分で制御できない値には unknown を使ってください。実際に使用するものに絞ったインターフェースを作成してください。

any よりよい代替手段

代わりに使うもの
不明な値に anyunknown(型を絞り込む必要がある)
any[]unknown[] または具体的な型
(x: any) => any適切な関数シグネチャ
Record<string, any>Record<string, unknown>
JSON に anyunknown を使って解析・検証する

危険信号 — 立ち止まって再検討してください

  • 1つの関数に複数の any 型がある
  • エラーを黙らせるために as any を使っている
  • 型チェックを回避するために // @ts-ignore または @ts-expect-error を使っている
  • 公開 API のシグネチャに any がある
  • 関数の戻り値の型に any がある

よくある正当化(どれも不適切です)

言い訳実際のところ
「実行時には動く」型は実行時より前にバグを見つけるためにあります。
「TypeScript は厳しすぎる」TypeScript はあなたを守っています。何を伝えているのか理解しましょう。
「型がわからない」unknown を使い、型を絞り込んでください。
「サードパーティライブラリだから」使用するものに必要な最小限の型定義を書いてください。
「内部コードにすぎない」内部コードもコードです。いずれデバッグすることになります。

クイックリファレンス

症状対応
理解できない型エラーエラーを注意深く読み、unknown を使う
複雑な入れ子の型小さなインターフェースに分割する
API からの動的なデータレスポンスの型を定義し、境界で検証する
JavaScript からの移行unknown から始め、段階的に型を追加する

結論

any はすべて、いつか発生するバグの種です。

わからない値には unknown を使い、わかっている値には適切な型を使ってください。どうしても any を使う必要がある場合は、適用範囲を狭くし、理由を記録して、なくす計画を立ててください。

参考資料

Dan Vanderkam 著『Effective TypeScript』の項目5「any 型の使用を制限する」に基づいています。

コメント