mcpField
S
strict-typing

strict-typing

github.com/troykelly開発1238 回インストール41 週間前に更新
リポジトリ

strict-typing について

strict-typingは、TypeScript、Python、Go、Rust、Java、C#などを使う開発者向けのコーディングスキルです。型の逃げ道を避け、明示的な型指定、厳格な設定、実行時検証を促します。

主な機能

  1. 01anyやunknownなどの型逃れを回避
  2. 02関数の引数と戻り値に型を指定
  3. 03厳格な型チェック設定を推奨
  4. 04動的データの形状を定義して検証
  5. 05型定義のないライブラリに定義を追加

活用シーン

  1. 01型安全なTypeScriptやPythonの記述
  2. 02API応答や解析済みJSONの処理
  3. 03型宣言のないサードパーティライブラリの利用

インストール

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

$npx skills add https://github.com/troykelly/claude-skills --skill strict-typing

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

詳細

厳密な型付け

概要

any 型は使用しません。unknown を型ガードなしで使用しません。すべてを完全に型付けします。

基本原則: 型はコンパイラーが検証するドキュメントです。

このスキルの対象: TypeScript、Python(型ヒントを使用)、Go、Rust、Java、C#、および型付けが可能なすべての言語。

ルール

NEVER use any, unknown, or equivalent type escapes.
ALWAYS provide explicit, accurate types.
TAKE EXTRA TIME if needed to type correctly.

TypeScript の詳細

禁止するパターン
// NEVER
const data: any = fetchData();
const items: unknown[] = parseItems();
function process(input: any): any { }
const config = {} as any;
// @ts-ignore
// @ts-expect-error (unless truly necessary with documentation)
必須のパターン
// ALWAYS
interface UserData {
  id: string;
  name: string;
  email: string;
}

const data: UserData = fetchData();

function process<T extends Processable>(input: T): ProcessResult<T> {
  // ...
}
設定

tsconfig.json で strict モードが有効になっていることを確認します。

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "noUncheckedIndexedAccess": true
  }
}
サードパーティの型の扱い

ライブラリーの型がない場合:

// Create type definitions
declare module 'untyped-library' {
  export interface Config {
    option1: string;
    option2: number;
  }

  export function init(config: Config): void;
}

または、DefinitelyTyped に型を提供します。

動的データの扱い

API レスポンスや解析した JSON の場合:

// Define expected shape
interface ApiResponse {
  users: User[];
  pagination: Pagination;
}

// Use type guard for runtime validation
function isApiResponse(data: unknown): data is ApiResponse {
  return (
    typeof data === 'object' &&
    data !== null &&
    'users' in data &&
    Array.isArray((data as ApiResponse).users)
  );
}

// Use with validation
const response = await fetch('/api/users');
const data: unknown = await response.json();

if (!isApiResponse(data)) {
  throw new Error('Invalid API response');
}

// data is now typed as ApiResponse
実行時検証に Zod を使用する
import { z } from 'zod';

const UserSchema = z.object({
  id: z.string(),
  name: z.string(),
  email: z.string().email(),
});

type User = z.infer<typeof UserSchema>;

// Parse and validate
const user = UserSchema.parse(unknownData);
// user is now typed as User

Python の詳細

禁止するパターン
# NEVER
def process(data):  # Missing type hints
    pass

def fetch() -> Any:  # Using Any
    pass

from typing import Any
result: Any = compute()
必須のパターン
# ALWAYS
from typing import TypeVar, Generic, Protocol
from dataclasses import dataclass

@dataclass
class User:
    id: str
    name: str
    email: str

def process(data: User) -> ProcessResult:
    ...

T = TypeVar('T', bound='Processable')

def transform(items: list[T]) -> list[T]:
    ...
設定

厳密な mypy 設定を使用します。

# mypy.ini
[mypy]
strict = True
disallow_any_generics = True
disallow_untyped_defs = True
disallow_incomplete_defs = True
check_untyped_defs = True
disallow_untyped_decorators = True
warn_redundant_casts = True
warn_unused_ignores = True

Go の詳細

Go は静的型付け言語ですが、次の使用は避けます。

// AVOID
interface{} // empty interface
any         // Go 1.18+ alias for interface{}

// PREFER
type specific interfaces or concrete types

interface{} が本当に必要な場合は、その理由を記録し、型アサーションを追加します。

型付けが難しい場合

型付けが不可能に思える場合:

ステップ 1:設計を見直す
Is the type hard to express because the design is complex?
→ Consider simplifying the design
ステップ 2:ジェネリクスを使用する
// Instead of any
function process<T>(input: T): T {
  return input;
}
ステップ 3:ユニオン型を使用する
// Instead of any for multiple types
type Input = string | number | User;

function process(input: Input): void {
  if (typeof input === 'string') {
    // input is string
  } else if (typeof input === 'number') {
    // input is number
  } else {
    // input is User
  }
}
ステップ 4:型ガードを作成する
function isUser(value: unknown): value is User {
  return (
    typeof value === 'object' &&
    value !== null &&
    'id' in value &&
    'name' in value
  );
}
ステップ 5:記録して正当化する(最終手段)

any が本当に避けられない場合(極めてまれです):

// JUSTIFIED: Third-party library `foo` has no types and
// creating accurate types requires reverse-engineering
// the entire library. See issue #123 for type contribution.
// TODO(#456): Remove when @types/foo is available
const result: any = thirdPartyCall();

このようなケースは例外的にまれであるべきです。

所要時間

適切な型付けには時間がかかります。それで問題ありません。

状況許容される時間
シンプルなインターフェース5 分
複雑なジェネリック30 分
型ガード15 分
ライブラリーの型1 時間

型付けにさらに時間がかかる場合は、設計を見直す必要があるかもしれません。

チェックリスト

コードをコミットする前に:

  • any 型を使用していない
  • 型ガードのない unknown を使用していない
  • @ts-ignore または # type: ignore を使用していない
  • すべての関数のパラメーターに型を付けている
  • すべての関数の戻り値に型を付けている
  • 公開するすべてのインターフェース/型をエクスポートしている
  • 型設定が厳密である

よくある言い訳への回答

言い訳回答
「一時的なものです」一時的なコードは恒久的なものになります。今すぐ型を付けましょう。
「型は後で修正します」後でその機会は訪れません。今すぐ型を付けましょう。
「any のほうが速いです」技術的負債によって遅くなります。今すぐ型を付けましょう。
「ライブラリーに型がありません」型を作成するか、Zod を使用しましょう。
「複雑すぎて型を付けられません」設計をシンプルにしましょう。

統合

このスキルは次によって適用されます:

  • issue-driven-development - ステップ 7

このスキルによって、次のことが実現します:

  • 自己文書化コード
  • コンパイル時のエラー検出
  • 安全なリファクタリング
  • IDE のサポート向上

コメント