mcpField
T
typescript-variables

typescript-variables

github.com/mkosir開発7854.0k 回インストール8 週間前に更新
リポジトリ

typescript-variables について

TypeScriptの変数に関するスタイル指針を、開発タスクに応じて適用、レビュー、説明するスキルです。constアサーション、ユニオン型、nullとundefinedの使い分けを扱います。

主な機能

  1. 01タスクに応じた変数規約の適用
  2. 02constアサーションの優先
  3. 03リテラルユニオン型の活用
  4. 04複数の真偽値による状態表現の回避
  5. 05nullとundefinedの区別

活用シーン

  1. 01定数オブジェクトや配列のリテラル型保持
  2. 02ユニオン型による排他的状態の表現
  3. 03値が未指定か空かの明確化

インストール

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

$npx skills add https://github.com/mkosir/typescript-style-guide --skill typescript-variables

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

詳細

変数

現在のタスクの状況に合わせて、TypeScript スタイルガイドの変数に関する規約を適用してください。

ワークフロー

  1. 対象リポジトリで使用されている規約と設定を確認します。
  2. リポジトリで明示されている規約がある場合は、この意見に基づくガイドラインより優先します。
  3. タスクに関係するガイドラインのみを適用、確認、または説明します。
  4. 適切な選択が状況や判断によって異なる場合は、重要なトレードオフを示します。

適用範囲

  • 自動で適用できるチェックは、TypeScript と ESLint に任せます。
  • このガイドが有効だからといって、関係のない TypeScript スタイルガイドの規約を適用しないでください。

関連ガイダンス

アプリケーションの状態

異なるデータを必要とする状態について詳しくは、利用可能であれば typescript-discriminated-unions を参照してください。

変数

const アサーション

定数は as const の const アサーションを使って宣言するよう努めてください。

定数は変更を意図しない値を表すために使われ、コードベースの信頼性と一貫性を高めます。const アサーションはリテラル型を保持し、読み取り専用のプロパティを推論します。

  • 型の絞り込み — as const を使うと、リテラル値(数値や文字列など)が、number や string のような一般化された型ではなく、厳密な値として扱われます。
  • 読み取り専用プロパティ — オブジェクトと配列のプロパティが読み取り専用になり、TypeScript が直接の変更を検出します。

例:

  • オブジェクト

    // ❌ Avoid
    const FOO_LOCATION = { x: 50, y: 130 }; // Type { x: number; y: number; }
    FOO_LOCATION.x = 10;
    
    // ✅ Use
    const FOO_LOCATION = { x: 50, y: 130 } as const; // Type '{ readonly x: 50; readonly y: 130; }'
    FOO_LOCATION.x = 10; // Error
    
  • 配列

    // ❌ Avoid
    const BAR_LOCATION = [50, 130]; // Type number[]
    BAR_LOCATION.push(10);
    
    // ✅ Use
    const BAR_LOCATION = [50, 130] as const; // Type 'readonly [50, 130]'
    BAR_LOCATION.push(10); // Error
    
  • テンプレートリテラル

    // ❌ Avoid
    const RATE_LIMIT = 25;
    const RATE_LIMIT_MESSAGE = `Max number of requests/min is ${RATE_LIMIT}.`; // Type string
    
    // ✅ Use
    const RATE_LIMIT = 25;
    const RATE_LIMIT_MESSAGE = `Max number of requests/min is ${RATE_LIMIT}.` as const; // Type 'Max number of requests/min is 25.'
    
enum と const アサーション

enum は、実行時コストや特有の問題があるため、TypeScript エコシステムでは推奨されません。
TypeScript のドキュメントでは、いくつかの落とし穴が説明されています。また、TypeScript 5.8 では、enum など実行時コードを生成する機能を無効にする --erasableSyntaxOnly フラグが導入されました。

{'no-restricted-syntax': [ 'error', { selector: 'TSEnumDeclaration', message: 'Replace enum with a literal type or a const assertion.', }, ]}

一般的には、次の方法を優先してください。

  • 可能な場合はリテラル型を使います。
  • 値をループ処理する場合は、const アサーションを付けた配列を使います。
  • 任意の値を列挙する場合は、const アサーションを付けたオブジェクトを使います。

例:

  • 実行時オブジェクトを避け、バンドルサイズを削減するには、リテラル型を使います。

    // ❌ Avoid using enums as they increase the bundle size
    enum UserRole {
      GUEST = 'guest',
      MODERATOR = 'moderator',
      ADMINISTRATOR = 'administrator',
    }
    
    // Transpiled JavaScript
    ('use strict');
    var UserRole;
    (function (UserRole) {
      UserRole['GUEST'] = 'guest';
      UserRole['MODERATOR'] = 'moderator';
      UserRole['ADMINISTRATOR'] = 'administrator';
    })(UserRole || (UserRole = {}));
    
    // ✅ Use literal types - Types are stripped during transpilation
    type UserRole = 'guest' | 'moderator' | 'administrator';
    
    const isGuest = (role: UserRole) => role === 'guest';
    
  • 値をループ処理する場合は、const アサーションを付けた配列を使います。

    // ❌ Avoid using enums
    enum USER_ROLES {
      guest = 'guest',
      moderator = 'moderator',
      administrator = 'administrator',
    }
    
    // ✅ Use const assertions arrays
    const USER_ROLES = ['guest', 'moderator', 'administrator'] as const;
    type UserRole = (typeof USER_ROLES)[number];
    
    const seedDatabase = () => {
      USER_ROLES.forEach((role) => {
        db.roles.insert(role);
      }
    }
    const insert = (role: UserRole) => {...
    
    const UsersRoleList = () => {
      return (
        <div>
          {USER_ROLES.map((role) => (
            <Item key={role} role={role} />
          ))}
        </div>
      );
    };
    const Item = ({ role }: { role: UserRole }) => {...
    
  • 任意の値を列挙する場合は、const アサーションを付けたオブジェクトを使います。

    // ❌ Avoid using enums
    enum COLORS {
      primary = '#B33930',
      secondary = '#113A5C',
      brand = '#9C0E7D',
    }
    
    // ✅ Use const assertions objects
    const COLORS = {
      primary: '#B33930',
      secondary: '#113A5C',
      brand: '#9C0E7D',
    } as const;
    
    type Colors = typeof COLORS;
    type ColorKey = keyof Colors; // Type "primary" | "secondary" | "brand"
    type ColorValue = Colors[ColorKey]; // Type "#B33930" | "#113A5C" | "#9C0E7D"
    
    const setColor = (color: ColorValue) => {...
    
    setColor(COLORS.primary);
    setColor('#B33930');
    
型のユニオンとブールフラグ

複数の選択肢が相互に排他的な場合は特に、ブール型のフラグ変数を複数使うのではなく、型のユニオンを活用してください。

ブールフラグは時間とともに増えやすく、アプリケーションの実際の状態が見えにくくなるため、コードが分かりにくく、エラーも起こりやすくなります。

// ❌ Avoid introducing multiple boolean flag variables
const isPending, isProcessing, isConfirmed, isExpired;

// ✅ Use type union variable
type UserStatus = 'pending' | 'processing' | 'confirmed' | 'expired';
const userStatus: UserStatus;

状態値だけが変わる場合はリテラルユニオンを使います。それぞれの状態で異なるデータが必要な場合は、判別可能ユニオンを使って有効な状態を明示的に表現してください。

null と undefined

strictNullChecks を有効にすると、null と undefined はそれぞれ異なる型と意味を持ちます。アプリケーションにおける値の不在の意味に応じて、一貫して使い分けてください。
次のようにすることを推奨します。

  • 代入や関数の戻り値など、値が明示的に空であることを表す場合は null を使います。
  • フォームのオプショナルフィールド、リクエストペイロード、データベースクエリなど、値が欠落または省略されていることを表す場合は undefined を使います(Prisma の使い分け)。

コメント