typescript-quality について
TypeScriptのコード品質を高めるためのクイックリファレンススキルです。リンティング、フォーマット、厳格な型チェック、コミット前のワークフローを設定する開発者向けに、BiomeとESLintの比較や設定、トラブルシューティングをまとめています。
主な機能
- 01BiomeとESLintの設定ガイド
- 02TypeScript厳格モードの設定
- 03コードスメルとアンチパターンの例
- 04Huskyとlint-stagedによるコミット前チェック
- 05トラブルシューティングと品質指標
活用シーン
- 01TypeScriptプロジェクトのリンターを選定
- 02より厳格なコンパイラチェックを有効化
- 03コミット前のコードチェックを設定
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill typescript-qualityインストール後、Claude Code で/typescript-qualityを入力して読み込まれたか確認します。
詳細
TypeScript の品質 - クイックリファレンス
このスキルを使用しない場合
- SonarQube との統合 -
sonarqubeスキルを使用してください - テストの設定 -
vitestスキルを使用してください - セキュリティスキャン - セキュリティ関連のスキルを使用してください
- React 固有のパターン -
reactスキルを使用してください
詳細な知識:包括的なドキュメントを参照するには、technology に
typescriptまたはbiomeを指定してmcp__documentation__fetch_docsを使用してください。
ツールの比較
| ツール | 速度 | 型認識 | 設定 |
|---|---|---|---|
| Biome | 最速 | いいえ | 最小限 |
| ESLint | 遅め | はい(TS 使用時) | 広範 |
| TypeScript | 該当なし | はい | tsconfig.json |
推奨:フォーマットと基本的なリントには Biome を、型認識ルールには ESLint を使用してください。
Biome のセットアップ(推奨)
インストール
npm install -D @biomejs/biome
npx biome init
biome.json
{
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
"organizeImports": { "enabled": true },
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noExcessiveCognitiveComplexity": {
"level": "warn",
"options": { "maxAllowedComplexity": 15 }
}
},
"suspicious": {
"noExplicitAny": "error",
"noImplicitAnyLet": "error"
},
"style": {
"noNonNullAssertion": "warn",
"useConst": "error"
}
}
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"trailingCommas": "es5",
"semicolons": "always"
}
}
}
コマンド
# Check all
npx biome check .
# Fix auto-fixable
npx biome check --write .
# Format only
npx biome format --write .
# Lint only
npx biome lint .
# CI mode (no write)
npx biome ci .
ESLint のセットアップ(型認識)
インストール
npm install -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
eslint.config.js(フラット設定 - ESLint 9+)
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.strictTypeChecked,
...tseslint.configs.stylisticTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
rules: {
// Type safety
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unsafe-assignment': 'error',
'@typescript-eslint/no-unsafe-call': 'error',
'@typescript-eslint/no-unsafe-member-access': 'error',
'@typescript-eslint/no-unsafe-return': 'error',
// Best practices
'@typescript-eslint/explicit-function-return-type': 'warn',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/await-thenable': 'error',
'@typescript-eslint/no-misused-promises': 'error',
// Code quality
'complexity': ['warn', { max: 10 }],
'max-depth': ['warn', { max: 4 }],
'max-lines-per-function': ['warn', { max: 50 }],
},
},
{
ignores: ['dist/', 'node_modules/', '*.config.js'],
}
);
コマンド
# Lint
npx eslint .
# Fix auto-fixable
npx eslint --fix .
# Show rule details
npx eslint --print-config src/index.ts
TypeScript の厳格モード
tsconfig.json(最大限の厳格さ)
{
"compilerOptions": {
// Strict type checking
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noPropertyAccessFromIndexSignature": true,
// Additional checks
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
// Module resolution
"moduleResolution": "bundler",
"module": "ESNext",
"target": "ES2022",
// Interop
"esModuleInterop": true,
"isolatedModules": true,
"verbatimModuleSyntax": true
}
}
主要な厳格フラグの説明
| フラグ | 効果 | 例 |
|---|---|---|
noUncheckedIndexedAccess | 配列へのアクセスは T | undefined を返します | arr[0] は T | undefined です |
exactOptionalPropertyTypes | { a?: string } は string またはプロパティなしを意味し、undefined ではありません | undefined を明示的に代入できません |
noPropertyAccessFromIndexSignature | インデックスシグネチャにはブラケット記法を強制します | obj.key ではなく obj['key'] |
よくあるコードの問題と修正方法
1. any の過剰な使用
// BAD
function process(data: any): any {
return data.value;
}
// GOOD
interface DataItem {
value: string;
}
function process(data: DataItem): string {
return data.value;
}
// GOOD - When truly unknown
function process(data: unknown): string {
if (typeof data === 'object' && data !== null && 'value' in data) {
return String((data as { value: unknown }).value);
}
throw new Error('Invalid data');
}
2. 型アサーションの過剰な使用
// BAD
const user = response.data as User;
// GOOD - Use type guards
function isUser(data: unknown): data is User {
return (
typeof data === 'object' &&
data !== null &&
'id' in data &&
'email' in data
);
}
if (isUser(response.data)) {
// response.data is User here
}
// GOOD - Use Zod for runtime validation
import { z } from 'zod';
const UserSchema = z.object({
id: z.string(),
email: z.string().email(),
});
const user = UserSchema.parse(response.data);
3. 非 null アサーション
// BAD
const element = document.getElementById('app')!;
// GOOD
const element = document.getElementById('app');
if (!element) {
throw new Error('App element not found');
}
// GOOD - Optional chaining when appropriate
const value = element?.textContent ?? 'default';
4. 複雑な条件式
// BAD
if (user && user.isActive && user.role === 'admin' && !user.suspended) {
// ...
}
// GOOD - Extract to function
function canAccessAdmin(user: User | null): user is User {
return (
user !== null &&
user.isActive &&
user.role === 'admin' &&
!user.suspended
);
}
if (canAccessAdmin(user)) {
// ...
}
5. 長い関数
// BAD - 100+ line function
async function processOrder(order: Order) {
// validation
// calculation
// database operations
// notifications
// logging
}
// GOOD - Split responsibilities
async function processOrder(order: Order) {
validateOrder(order);
const total = calculateTotal(order);
await saveOrder(order, total);
await notifyUser(order);
logOrderProcessed(order);
}
コミット前のセットアップ
package.json のスクリプト
{
"scripts": {
"lint": "biome check .",
"lint:fix": "biome check --write .",
"typecheck": "tsc --noEmit",
"quality": "npm run typecheck && npm run lint"
}
}
Husky + lint-staged
npm install -D husky lint-staged
npx husky init
// package.json
{
"lint-staged": {
"*.{ts,tsx,js,jsx}": [
"biome check --write --no-errors-on-unmatched"
]
}
}
# .husky/pre-commit
npx lint-staged
VS Code の設定
// .vscode/settings.json
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "explicit",
"quickfix.biome": "explicit"
},
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}
品質指標の目標
| 指標 | 目標 | ツール |
|---|---|---|
| 循環的複雑度 | < 10 | ESLint complexity ルール |
| 認知的複雑度 | < 15 | Biome/SonarQube |
| 関数の長さ | < 50 行 | ESLint max-lines-per-function |
| ファイルの長さ | < 300 行 | ESLint max-lines |
| ネストの深さ | < 4 階層 | ESLint max-depth |
| パラメーター数 | < 4 | ESLint max-params |
アンチパターン
| アンチパターン | 問題点 | 適切な方法 |
|---|---|---|
あらゆる場所で any を使う | 型安全性が損なわれます | 適切な型または unknown を使用してください |
as による型アサーション | 実行時エラーにつながります | 型ガードまたは Zod を使用してください |
! による非 null アサーション | 実行時に null となる可能性があります | 適切な null チェックを行ってください |
| lint ルールをインラインで無効化する | 技術的負債につながります | 問題を修正するか、グローバルに設定してください |
@ts-ignore | 実際のエラーを隠します | コメントを添えて @ts-expect-error を使用してください |
| 厳格モードを使わない | 保証が弱くなります | すべての厳格フラグを有効にしてください |
よくある問題の解決方法
| 問題 | 考えられる原因 | 解決策 |
|---|---|---|
| 大規模なプロジェクトで ESLint が遅い | 型認識ルールの処理コストが高い | プロジェクト参照とキャッシュを使用してください |
| Biome と ESLint が競合する | 両方がフォーマットしようとしている | フォーマットには Biome を、型ルールには ESLint を使用してください |
| TypeScript のエラーを lint で検出できない | 型認識ルールが必要 | projectService を使用して typescript-eslint を設定してください |
| import の順序が一定しない | 自動整理が無効 | Biome の organizeImports を有効にしてください |
| コミット前の処理が遅すぎる | すべてのファイルを処理している | 変更されたファイルのみを対象にするため lint-staged を使用してください |
関連スキル
コメント
Markdown 対応