mcpField
T
typescript-conventions

typescript-conventions

github.com/exceptionless開発2.5k48 回インストール今日更新
リポジトリ

typescript-conventions について

コーディングエージェントがプロジェクトの書式、命名、インポート、型安全性の規約に従うための TypeScript スキルです。Promise の処理、制御構文、エクスポート方法も定めています。

主な機能

  1. 01書式と差分最小化の規則
  2. 02ファイル命名とインポートの方針
  3. 03型安全性を重視し any を回避
  4. 04Promise の明示的な処理
  5. 05制御構文とエクスポートの統一

活用シーン

  1. 01TypeScript のコード変更を規約に沿って作成
  2. 02名前やインポートの一貫性を確認
  3. 03型定義とエラー処理を整備
  4. 04非同期コードとエクスポート方法を統一

インストール

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

$npx skills add https://github.com/exceptionless/exceptionless --skill typescript-conventions

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

詳細

TypeScript の規約

スタイルとフォーマット

  • .editorconfig と ESLint + Prettier の設定を厳守してください
  • コミット前に npm run format を実行してください
  • 差分を最小限にする:必要な箇所のみ変更し、既存のフォーマットと構造を維持してください
  • 周囲のコードスタイルに正確に合わせてください

プロジェクトのフロントエンド規則

  • すべての制御フロー文(if、for、while など)で、必ず波括弧を使用してください。
  • 文を返すアロー関数では、必ずブロック本体を使用してください。プロジェクトコードでは、単一式の省略記法を避けてください。
  • 識別子で略語を使用しないでください(org ではなく organization、filt ではなく filter)。
  • 1 行に条件式と return を記述する形式は避け、読みやすい複数行のブロックを使用してください。

ファイルの命名

  • ファイルとディレクトリには kebab-case を使用してください
  • コンポーネントファイル:user-profile.svelte
  • TypeScript ファイル:api-client.ts、user-service.ts
  • テストファイル:user-service.test.ts または user-service.spec.ts

インポート

名前付きインポートを優先
// ✅ Good: Named imports
import { UserService, type User } from "$lib/services/user-service";
import { formatDate, formatNumber } from "$lib/utils/formatters";

// ❌ Avoid: Namespace imports (except allowed exceptions)
import * as utils from "$lib/utils";
  • ほとんどのモジュールでは名前付きインポートを優先してください。名前空間インポートは、承認済みのパターン(shadcn の複合インポートなど)に限定してください。
許可される名前空間インポート
// ✅ Allowed: shadcn-svelte components
import * as Dialog from "$comp/ui/dialog";
import * as DropdownMenu from "$comp/ui/dropdown-menu";

// ✅ Allowed: Barrel exports
import * as Field from "$comp/ui/field";

型安全性

any を避ける
// ❌ Bad
function processData(data: any) { ... }

// ✅ Good: Use interfaces/types
interface UserData {
    id: string;
    name: string;
    email: string;
}

function processData(data: UserData) { ... }

// ✅ Good: Use unknown for truly unknown data
function parseResponse(data: unknown): UserData {
    if (isUserData(data)) {
        return data;
    }
    throw new Error('Invalid data format');
}
型ガード
function isUserData(data: unknown): data is UserData {
    return (
        typeof data === "object" &&
        data !== null &&
        "id" in data &&
        "name" in data &&
        "email" in data
    );
}

// Discriminated unions
type ApiResponse =
    | { status: "success"; data: UserData }
    | { status: "error"; error: string };

function handleResponse(response: ApiResponse) {
    if (response.status === "success") {
        // TypeScript knows response.data exists
        return response.data;
    }
    // TypeScript knows response.error exists
    throw new Error(response.error);
}

Promise の処理

必ず await する
// ✅ Good: Always await
const user = await fetchUser(id);
const [users, projects] = await Promise.all([fetchUsers(), fetchProjects()]);

// ❌ Bad: Fire and forget without handling
fetchUser(id); // Exception is lost!
エラー処理
// ✅ Good: try/catch with proper typing
async function loadUser(id: string): Promise<User | null> {
    try {
        const response = await api.get<User>(`/users/${id}`);
        return response.data;
    } catch (error) {
        if (error instanceof ApiError) {
            console.error("API Error:", error.message);
        }
        return null;
    }
}

制御文

1 行の制御文には、すべて波括弧が必要です。

// ✅ Good: Always use braces
if (condition) {
    doSomething();
}

for (const item of items) {
    process(item);
}

// ❌ Bad: No braces
if (condition) doSomething();

インターフェースの命名

API 関連の型には、HTTP 動詞の接頭辞を使用してください。

// Request/Response interfaces
interface PostOrganizationRequest {
    name: string;
    billing_email: string;
}

interface GetOrganizationParams {
    id: string;
}

interface PatchUserRequest {
    name?: string;
    email?: string;
}

エクスポートのパターン

// Named exports preferred
export function createUser(data: CreateUserRequest): Promise<User> { ... }
export type { User, CreateUserRequest };

// Re-export from barrel files
// src/lib/features/users/index.ts
export { createUser, updateUser, deleteUser } from './api.svelte';
export type { User, CreateUserRequest } from './models';

モダンな ES6 以降の機能

// Template literals
const message = `Hello, ${user.name}!`;

// Destructuring
const { id, name, email } = user;
const [first, ...rest] = items;

// Nullish coalescing
const displayName = user.nickname ?? user.name ?? "Anonymous";

// Optional chaining
const city = user?.address?.city;

// Object shorthand
const data = { id, name, createdAt: new Date() };

コメント