mcpField
A
avoid-unnecessary-type-params

avoid-unnecessary-type-params

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

avoid-unnecessary-type-params について

ジェネリック関数や型を見直す TypeScript 開発者向けのスキルです。不要な型パラメーターが複雑さを増し、推論を妨げ、型の関係を示さないまま安全性を誤認させる点を説明します。

主な機能

  1. 01一度しか使われない型パラメーターの特定
  2. 02型の関係を作るジェネリックの原則
  3. 03型の弱い入力に unknown を提案
  4. 04ジェネリック関数シグネチャの簡素化
  5. 05推論を改善するかどうかの確認

活用シーン

  1. 01ジェネリック API シグネチャのレビュー
  2. 02型推論がうまくいかない原因の調査
  3. 03コード内の不要なジェネリックの削減

インストール

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

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

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

詳細

不要使いない型パラメーターを避ける

概要

「ジェネリクスの黄金律」では、型パラメーターは関数シグネチャに2回以上登場するべきだとされています。型パラメーターが1回しか登場しない場合、何も関連付けておらず、不要である可能性が高いです。不要な型パラメーターは、誤った型安全性を感じさせ、型推論の成功率を下げることがあります。

このスキルは、余分な型パラメーターを見つけて取り除き、TypeScriptがより効果的に推論できる、より簡潔で保守しやすいコードを書くのに役立ちます。

このスキルを使う場面

  • ジェネリック関数や型を書くとき
  • 型シグネチャの明確さをレビューするとき
  • 型パラメーターが宣言以外で1回しか登場しないとき
  • 「柔軟性」のためにジェネリクスを追加したくなったとき
  • 型推論がうまくいかない原因を調査するとき

絶対のルール

型パラメーターは、関係性を確立するために2回以上登場する必要があります。型パラメーターが1回しか登場しない場合、本当に必要かどうかを慎重に見直してください。

検出

次のようなパターンに注意してください。

// RED FLAGS - Unnecessary type parameters
function parseYAML<T>(input: string): T;  // Return-only generic
type Fn = <T>(x: T) => void;  // T only used once
function third<A, B, C>(a: A, b: B, c: C): C;  // A and B appear once
function getLength<T extends Lengthy>(x: T): number;  // T only in parameter

黄金律

型パラメーターは型同士を関連付けるためのものです。型パラメーターが1回しか登場しない場合、何も関連付けていません。

// GOOD: T appears twice, relating input and output
function identity<T>(arg: T): T {
  return arg;
}

// BAD: T only appears once (in return type)
function parseYAML<T>(input: string): T;
// Equivalent to: function parseYAML(input: string): any

// Usage shows the problem:
const data: User = parseYAML('...');  // Looks safe, but T can be anything
const bad: Banana = parseYAML('...');  // Also "valid" - no error!

戻り値のみに使うジェネリクス

戻り値のみに使うジェネリクスは、明示的な as を使わない型アサーションと同等なので危険です。

// BAD: Return-only generic
declare function parseYAML<T>(input: string): T;
const user: User = parseYAML('...');  // No error, but no validation either

// GOOD: Return unknown, force explicit assertion
declare function parseYAML(input: string): unknown;
const user = parseYAML('...') as User;  // Explicit about the assertion

// Or use validation:
const user = parseYAML('...');
if (isUser(user)) {  // Type guard
  // user is User here
}

不要なジェネリクスをシンプルにする

// BEFORE: Unnecessary type parameters
function third<A, B, C>(a: A, b: B, c: C): C {
  return c;
}

// AFTER: Only keep C which appears twice
function third<C>(a: unknown, b: unknown, c: C): C {
  return c;
}

ジェネリクスが必要な場合

// GOOD: K appears twice, relating parameter to return type
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

// K appears in: parameter type (key: K) and return type (T[K])
// This IS a good use of generics

クラスのジェネリクス

// GOOD: T appears multiple times, relating class properties
class Container<T> {
  private items: T[] = [];
  add(item: T): void { this.items.push(item); }
  getAll(): T[] { return this.items; }
}

// BAD: T only used in one method
class Joiner<T extends string | number> {
  join(els: T[]): string {
    return els.map(String).join(',');
  }
}
// Better: Move T to method or use concrete type
class Joiner {
  join(els: (string | number)[]): string {
    return els.map(String).join(',');
  }
}
// Best: Just a function
function join(els: (string | number)[]): string {
  return els.map(String).join(',');
}

圧力に負けないための手順

「柔軟な」ジェネリクスを追加するよう求められたときは、次の点を確認してください。

  1. 登場回数を数える:型パラメーターは2回以上登場しますか?
  2. 関係性を確認する:複数の値の型を関連付けていますか?
  3. unknownを検討する:unknown でも同じように使えますか?
  4. 型推論をテストする:ジェネリクスによって型推論は改善しますか、それとも悪化しますか?

注意すべきパターン

アンチパターン問題点
function f<T>(): T戻り値のみに使用され、型安全性がありません
type Fn = <T>(x: T) => void戻り値でTを使用しておらず、不要です
1回しか使わない型に対するジェネリクス利点がないのに複雑さが増します
Tが1回しか登場しない T extends X制約が役に立ちません

よくある正当化

「APIの柔軟性が高まります」

実際のところ:不要なジェネリクスは、誤った安全性を感じさせます。実際の柔軟性は高めず、混乱を招くだけです。

「後で必要になるかもしれません」

実際のところ:先回りして追加するのではなく、必要になったときにジェネリクスを追加してください。後からいつでも追加できます。

「よりプロフェッショナルに見えます」

実際のところ:複雑で不要な型よりも、シンプルで正確な型のほうがプロフェッショナルです。

クイックリファレンス

パターン判定修正方法
function f<T>(x: T): T✓ 良いTが入力と出力を関連付けています
function f<T>(x: string): T✗ 悪いunknown または具体的な型を使います
function f<T>(x: T): void✗ 悪いunknown または any を使います
class C<T> { method(x: T): T }✓ 良いTが複数箇所の使用を関連付けています
class C<T> { method(x: T): void }✗ 悪いTをメソッドに移すか、削除します

要点

ジェネリクスの第一のルールは「使わないこと」です。型パラメーター同士の関係性を確立するときだけ追加してください。型パラメーターが1回しか登場しない場合は削除しましょう。そうすることで、コードがより簡潔になり、型推論も改善します。

参考資料

  • Dan Vanderkam著『Effective TypeScript, 2nd Edition』
  • 項目51:不要な型パラメーターを避ける

コメント