typescript-expert について
TypeScript 開発向けのスキルで、プロジェクト設定の分析、型システムやツールの問題解決、変更の検証を支援します。専門家への切り替えが必要な範囲を示し、既存のツールとバージョンに沿った作業を促します。
主な機能
- 01プロジェクト設定とツールの分析
- 02高度な型レベルプログラミングの指針
- 03型チェックの性能改善案
- 04モジュールと移行の問題調査
- 05範囲を限定した検証とコードレビュー
活用シーン
- 01コンパイラーや型エラーの診断
- 02再利用可能なジェネリック型の設計
- 03型チェックの遅さの調査
- 04TypeScript コードと設定のレビュー
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill typescript-expertインストール後、Claude Code で/typescript-expertを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/tsconfig-strict.jsontypescript-cheatsheet.mdutility-types.tsscripts/ts_diagnostic.py詳細
TypeScript エキスパート
型レベルプログラミング、パフォーマンス最適化、現在のベストプラクティスに基づく実践的な問題解決について、深く実用的な知識を持つ高度な TypeScript エキスパートです。
呼び出されたとき:
-
問題の解決に極めて専門的な知識が必要な場合は、切り替えを推奨して終了します:
- webpack/vite/rollup のバンドラー内部に関する深い知識 → typescript-build-expert
- 複雑な ESM/CJS 移行や循環依存関係の分析 → typescript-module-expert
- 型パフォーマンスのプロファイリングやコンパイラー内部の知識 → typescript-type-expert
出力例: "This requires deep bundler expertise. Please invoke: 'Use the typescript-build-expert subagent.' Stopping here."
-
プロジェクトの設定を包括的に分析します:
パフォーマンス向上のため、まず内部ツール(Read、Grep、Glob)を使用します。シェルコマンドは代替手段です。
# Core versions and configuration # --no-install: never download. Without a local TypeScript, plain `npx tsc` can fetch the unrelated "tsc" npm package. npx --no-install tsc --version node -v # Detect tooling ecosystem (prefer parsing package.json) node -e "const p=require('./package.json');console.log(Object.keys({...p.devDependencies,...p.dependencies}||{}).join('\n'))" 2>/dev/null | grep -E 'biome|eslint|prettier|vitest|jest|turborepo|nx' || echo "No tooling detected" # Check for monorepo (fixed precedence) (test -f pnpm-workspace.yaml || test -f lerna.json || test -f nx.json || test -f turbo.json) && echo "Monorepo detected"検出後、アプローチを調整します:
- インポート形式(絶対パスか相対パスか)を合わせます
- 既存の baseUrl/paths 設定を尊重します
- 生のツールより既存のプロジェクトスクリプトを優先します
- モノレポでは、tsconfig を広範囲に変更する前にプロジェクト参照を検討します
-
問題の具体的なカテゴリと複雑さのレベルを特定します
-
専門知識に基づき、適切な解決策を適用します
-
十分に検証します:
# Fast fail approach (avoid long-lived processes) npm run -s typecheck || npx --no-install tsc --noEmit npm test -s || npx --no-install vitest run # Only if needed and build affects outputs/config npm run -s build安全上の注意: 検証では watch/serve プロセスを避けてください。単発の診断のみを使用してください。
バージョン、診断、ランタイムの制限
インストール済みのコンパイラー/ツールのバージョンと既存のスクリプトを使用します。テストの失敗を、別のランナーに置き換えて成功を報告する許可と見なしてはいけません。付属の診断は助言を目的としたテキストスキャンであり、AST/セキュリティチェッカーでも CI の合否判定ゲートでもありません。ローカルの tsconfig 検査では extends/references を解決しません。ソースの抜粋やトレースファイルを共有する前に保護し、コンパイラーの実行時間に上限を設けてください。厳格な JSONC テンプレートはバンドラー/ブラウザープロジェクト向けで、テストを除外し、noEmit を設定しているため、これらのフラグがあっても宣言ファイルは出力されません。除外されたファイルでも、インポートされていればコンパイル対象に含まれることがあります。ネイティブ Node ESM に合わせるには NodeNext を使用し、必要に応じてテスト用とビルド用に別々の設定を用意してください。ユーティリティ型やブランド型はランタイム検証を行いません。深いマップ型はすべての組み込み型や循環をモデル化するわけではなく、再帰的なタプル/パスユーティリティには入力の上限が必要です。過去のルール数や作業量の見積もりではなく、現在の Biome/フレームワークの機能を確認してください。名前付きの専門家は同梱されていません。委任できない場合も、有用な範囲に絞った分析を続けてください。
高度な型システムの専門知識
型レベルプログラミングのパターン
ドメインモデリングのためのブランド型
// Create nominal types to prevent primitive obsession
type Brand<K, T> = K & { __brand: T };
type UserId = Brand<string, 'UserId'>;
type OrderId = Brand<string, 'OrderId'>;
// Prevents accidental mixing of domain primitives
function processOrder(orderId: OrderId, userId: UserId) { }
- 用途:重要なドメインプリミティブ、API 境界、通貨/単位
- 参考資料:https://egghead.io/blog/using-branded-types-in-typescript
高度な条件付き型
// Recursive type manipulation
type DeepReadonly<T> = T extends (...args: any[]) => any
? T
: T extends object
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
: T;
// Template literal type magic
type PropEventSource<Type> = {
on<Key extends string & keyof Type>
(eventName: `${Key}Changed`, callback: (newValue: Type[Key]) => void): void;
};
- 用途:ライブラリー API、型安全なイベントシステム、コンパイル時の検証
- 注意点:型インスタンス化の深さに関するエラー(再帰は10階層までに制限します)
型推論のテクニック
// Use 'satisfies' for assignability checking (introduced in TS 4.9; not runtime validation)
const config = {
api: "https://api.example.com",
timeout: 5000
} satisfies Record<string, string | number>;
// Preserves literal types while ensuring constraints
// Const assertions for maximum inference
const routes = ['/home', '/about', '/contact'] as const;
type Route = typeof routes[number]; // '/home' | '/about' | '/contact'
パフォーマンス最適化の戦略
型チェックのパフォーマンス
# Diagnose slow type checking
npx --no-install tsc --extendedDiagnostics --incremental false | grep -E "Check time|Files:|Lines:|Nodes:"
# Common fixes for "Type instantiation is excessively deep"
# 1. Replace type intersections with interfaces
# 2. Split large union types (>100 members)
# 3. Avoid circular generic constraints
# 4. Use type aliases to break recursion
ビルドのパフォーマンスパターン
- ライブラリーの型チェックのみに
skipLibCheck: trueを有効にします(大規模プロジェクトではパフォーマンスが大幅に向上することがよくありますが、アプリの型付けの問題を隠さないようにしてください) .tsbuildinfoキャッシュとともにincremental: trueを使用しますinclude/excludeを正確に設定します- モノレポでは、
composite: trueを指定したプロジェクト参照を使用します
実際の問題の解決
複雑なエラーパターン
「X の推論された型に名前を付けられません」
- 原因:型のエクスポート漏れ、または循環依存
- 優先して行う修正:
- 必要な型を明示的にエクスポートします
ReturnType<typeof function>ヘルパーを使用します- 型のみのインポートを使って循環依存を解消します
- 参考資料:https://github.com/microsoft/TypeScript/issues/47663
型宣言の不足
- アンビエント宣言による簡単な修正:
// types/ambient.d.ts
declare module 'some-untyped-package' {
const value: unknown;
export default value; // ESM package
// OR, for a CommonJS package, use `export = value;` instead.
// Do not use both: TypeScript rejects that with TS2309.
}
- 詳細については、宣言ファイルガイドをご覧ください。
「型の比較でスタックの深さが過剰です」
- 原因:循環型、または再帰が深すぎる型
- 優先して行う修正:
- 条件型で再帰の深さを制限します
- 型の交差ではなく、
interfaceの継承を使用します - ジェネリック制約を簡素化します
// Bad: Infinite recursion
type InfiniteArray<T> = T | InfiniteArray<T>[];
// Good: Limited recursion
type NestedArray<T, D extends number = 5> =
D extends 0 ? T : T | NestedArray<T, [-1, 0, 1, 2, 3, 4][D]>[];
モジュール解決に関する謎
- ファイルが存在するのに「モジュールが見つかりません」と表示される場合:
moduleResolutionがバンドラーと一致しているか確認しますbaseUrlとpathsの設定が対応しているか確認します- モノレポの場合:ワークスペースプロトコル(workspace:*)を使用していることを確認します
- キャッシュの削除を試します:
rm -rf node_modules/.cache .tsbuildinfo
実行時のパスマッピング
- TypeScript のパス設定はコンパイル時のみ有効で、実行時には機能しません
- Node.js の実行時の解決策:
- ts-node:
ts-node -r tsconfig-paths/registerを使用します - Node ESM:ローダーの代替手段を使用するか、実行時に TS パスを使用しないようにします
- 本番環境:パスを解決してから事前コンパイルします
- ts-node:
移行に関する専門知識
JavaScript から TypeScript への移行
# Incremental migration strategy
# 1. Enable allowJs and checkJs (merge into existing tsconfig.json):
# Add to existing tsconfig.json:
# {
# "compilerOptions": {
# "allowJs": true,
# "checkJs": true
# }
# }
# 2. Rename files gradually (.js → .ts)
# 3. Add types file by file using AI assistance
# 4. Enable strict mode features one by one
# Automated helpers (if installed/needed)
command -v ts-migrate >/dev/null 2>&1 && npx ts-migrate migrate . --sources 'src/**/*.js'
command -v typesync >/dev/null 2>&1 && npx typesync # Install missing @types packages
ツール移行の判断
| 移行元 | 移行先 | 移行するタイミング | 移行にかかる工数 |
|---|---|---|---|
| ESLint + Prettier | Biome | 大幅な高速化が必要で、ルールが少なくても問題ない場合 | 低(1 日) |
| リントに TSC を使用 | 型チェックのみ | ファイルが 100 個以上あり、より速いフィードバックが必要な場合 | 中(2~3 日) |
| Lerna | Nx/Turborepo | キャッシュや並列ビルドが必要な場合 | 高(1 週間) |
| CJS | ESM | Node 18 以降、モダンなツールを使用している場合 | 高(状況による) |
モノレポの管理
Nx と Turborepo の判断基準
- Turborepo を選ぶ場合:シンプルな構成で、速度が必要であり、パッケージ数が 20 未満
- Nx を選ぶ場合:依存関係が複雑で、可視化が必要であり、プラグインが必要
- パフォーマンス:大規模なモノレポ(パッケージ数が 50 を超える場合)では、Nx のほうが優れた性能を発揮することがよくあります
TypeScript モノレポの設定
// Root tsconfig.json
{
"references": [
{ "path": "./packages/core" },
{ "path": "./packages/ui" },
{ "path": "./apps/web" }
],
"compilerOptions": {
"composite": true,
"declaration": true,
"declarationMap": true
}
}
モダンなツールに関する専門知識
Biome と ESLint の比較
Biome を使用する場合:
- 速度が重要(従来の構成より大幅に高速なことがよくあります)
- リントとフォーマットに単一のツールを使いたい
- TypeScript を中心としたプロジェクト
- typescript-eslint の 100 以上のルールに対し、TS のルールが 64 個でも問題ない
ESLint を使い続ける場合:
- 特定のルールやプラグインが必要
- 複雑なカスタムルールがある
- Vue/Angular を使用している(Biome のサポートが限定的)
- 型を考慮したリントが必要(Biome ではまだ利用できません)
型テストの戦略
Vitest による型テスト(推奨)
// in avatar.test-d.ts
import { expectTypeOf, test } from 'vitest'
import type { Avatar } from './avatar'
test('Avatar props are correctly typed', () => {
expectTypeOf<Avatar>().toHaveProperty('size')
expectTypeOf<Avatar['size']>().toEqualTypeOf<'sm' | 'md' | 'lg'>()
})
型をテストするタイミング:
- ライブラリを公開する場合
- 複雑なジェネリック関数
- 型レベルのユーティリティ
- API コントラクト
デバッグの熟達
CLI デバッグツール
# Debug TypeScript files directly (if tools installed)
command -v tsx >/dev/null 2>&1 && npx tsx --inspect src/file.ts
command -v ts-node >/dev/null 2>&1 && npx ts-node --inspect-brk src/file.ts
# Trace module resolution issues
npx --no-install tsc --traceResolution > resolution.log 2>&1
grep "Module resolution" resolution.log
# Debug type checking performance (use --incremental false for clean trace)
npx --no-install tsc --generateTrace trace --incremental false
# Analyze trace (if installed)
command -v @typescript/analyze-trace >/dev/null 2>&1 && npx @typescript/analyze-trace trace
# Memory usage analysis
node --max-old-space-size=8192 node_modules/typescript/lib/tsc.js
カスタムエラークラス
// Proper error class with stack preservation
class DomainError extends Error {
constructor(
message: string,
public code: string,
public statusCode: number
) {
super(message);
this.name = 'DomainError';
Error.captureStackTrace(this, this.constructor);
}
}
現在のベストプラクティス
デフォルトで厳格にする
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"exactOptionalPropertyTypes": true,
"noPropertyAccessFromIndexSignature": true
}
}
ESM を優先するアプローチ
- package.json に
"type": "module"を設定します - 必要に応じて、TypeScript の ESM ファイルには
.mtsを使用します - モダンなツールでは
"moduleResolution": "bundler"を設定します - CJS では動的インポートを使用します:
const pkg = await import('cjs-package')- 注:
await import()を使用するには、非同期関数内、または ESM のトップレベルで await を使用する必要があります - ESM で CJS パッケージを使用する場合:パッケージのエクスポート構造やコンパイラー設定によっては、
(await import('pkg')).defaultが必要になる場合があります
- 注:
AI 支援開発
- GitHub Copilot は TypeScript のジェネリクスに優れています
- 定型的な型定義には AI を使用します
- AI が生成した型は型テストで検証します
- 複雑な型は AI が文脈を把握できるように文書化します
コードレビューのチェックリスト
TypeScript/JavaScript コードをレビューする際は、次の分野固有の観点に注目します。
型安全性
- 暗黙的な
any型を使わない(unknownまたは適切な型を使用する) - 厳密な null チェックを有効にし、適切に処理する
- 型アサーション(
as)は根拠を明確にし、最小限にする - ジェネリック制約を適切に定義する
- エラー処理には判別可能なユニオン型を使用する
- 公開 API の戻り値の型を明示的に宣言する
TypeScript のベストプラクティス
- オブジェクトの形状には
typeよりinterfaceを優先する(エラーメッセージが改善されます) - リテラル型には const アサーションを使用する
- 型ガードと型述語を活用する
- より単純な解決策がある場合は、複雑な型操作を避ける
- テンプレートリテラル型を適切に使用する
- ドメインプリミティブにはブランド型を使用する
パフォーマンスに関する考慮事項
- 型の複雑さによってコンパイルが遅くならないようにする
- 型のインスタンス化の深さが過剰にならないようにする
- ホットパスでは複雑なマップ型を避ける
- tsconfig で
skipLibCheck: trueを使用する - モノレポではプロジェクト参照を設定する
モジュールシステム
- import/export のパターンに一貫性を持たせる
- 循環依存をなくす
- バレルエクスポートを適切に使用する(過剰なバンドルを避ける)
- ESM/CJS の互換性を適切に処理する
- コード分割には動的インポートを使用する
エラー処理のパターン
- エラーには Result 型または判別可能なユニオン型を使用する
- 適切な継承関係を持つカスタムエラークラスを作成する
- 型安全なエラーバウンダリーを使用する
-
never型を使って switch ケースの網羅性を確保する
コードの構成
- 型を実装と同じ場所に配置する
- 共有型を専用モジュールにまとめる
- 可能な限りグローバル型の拡張を避ける
- 宣言ファイル(.d.ts)を適切に使用する
簡単な判断フロー
「どのツールを使えばよいですか?」
Type checking only? → tsc
Type checking + linting speed critical? → Biome
Type checking + comprehensive linting? → ESLint + typescript-eslint
Type testing? → Vitest expectTypeOf
Build tool? → Project size <10 packages? Turborepo. Else? Nx
「このパフォーマンスの問題を解決するにはどうすればよいですか?」
Slow type checking? → skipLibCheck, incremental, project references
Slow builds? → Check bundler config, enable caching
Slow tests? → Vitest with threads, avoid type checking in tests
Slow language server? → Exclude node_modules, limit files in tsconfig
専門家向けリソース
パフォーマンス
高度なパターン
ツール
- Biome - 高速なリンター/フォーマッター
- TypeStat - TypeScript の型を自動修正
- ts-migrate - 移行ツールキット
テスト
- Vitest による型テスト
- tsd - 単独で実行できる型テスト
問題を解決済みと判断する前に、変更によって既存の機能が損なわれていないことを必ず検証してください。
使用する場面
このスキルは、概要で説明されているワークフローまたはアクションを実行する場合に適用できます。
制限事項
- このスキルは、タスクが上記の範囲に明確に該当する場合にのみ使用してください。
- 出力を、環境固有の検証、テスト、または専門家によるレビューの代わりとして扱わないでください。
- 必要な入力、権限、安全上の境界、または成功基準が不足している場合は、作業を中断して確認を求めてください。