メインコンテンツまでスキップ

命名規則 ① ケース規約と変数・定数

本テーマは 3 部構成です

命名規則は 3 つの記事に分かれています。本記事 (第 1 部) ではケース規約と変数・真偽値・定数の命名を扱い、第 2 部: 関数とクラス第 3 部: 命名の質を高めると続きます。

なぜ変数名が大切なのか

良い変数名はコードそのものがドキュメントになることを可能にします。

❌ Bad: 意図が伝わらない

❌ Bad: 意図が伝わらない
const a = 300 / 60;

問題点:

  • a が何を表すのか不明
  • 30060 の意味が不明
  • コメントなしでは理解不可能

✅ Good: 意図が明確

✅ Good: 意図が明確
const minutes = 300;
const hours = minutes / 60;

改善点:

  • 変数名から「分を時間に変換」という意図が明確
  • 数値の単位が理解できる
  • コメント不要で自己説明的

命名が変わるとコードの意味が変わる


識別子とケース

識別子(変数名、関数名、クラス名など)の命名規則には主に4つのパターンがあります。

命名規則の種類

種類
ケバブケースkebab-case, user-name
スネークケースsnake_case, user_name
パスカルケースPascalCase, UserData
キャメルケースcamelCase, userName

1. ケバブケース(kebab-case)

説明: 単語と単語の間をハイフン(-)でつなぐ。

✅ Good: 使用場面: HTML属性、URL、CSSクラス名
// ✅ 使用場面: HTML属性、URL、CSSクラス名
<!-- HTML属性 -->
<input name="user-name" />
<section class="content-width">...</section>

<!-- URL -->
https://example.com/sales-profit
https://example.com/user-profile

TypeScript変数では使用しない (ハイフンが減算演算子と解釈される)

❌ Bad: エラー!
// ❌ エラー!
const user-name = "Taro"; // SyntaxError

2. スネークケース(snake_case)

説明: 単語と単語の間をアンダースコア(_)でつなぐ。

✅ Good: 使用場面(TypeScriptでは限定的)
// ✅ 使用場面(TypeScriptでは限定的)

TypeScriptでは一般的にキャメルケースが推奨されますが、以下の場合に使用されることがあります:

// データベースのカラム名に合わせる場合
interface UserRecord {
user_id: number;
first_name: string;
last_name: string;
created_at: Date;
}

// 外部APIのレスポンスに合わせる場合
type ApiResponse = {
access_token: string;
refresh_token: string;
expires_in: number;
};

アッパースネークケース(UPPER_SNAKE_CASE)

説明: 全て大文字でアンダースコアでつなぐ。

✅ Good: 使用場面: 定数(変更されない値)
// ✅ 使用場面: 定数(変更されない値)
const MAX_USER_COUNT = 100;
const API_BASE_URL = "https://api.example.com";
const DEFAULT_TIMEOUT_MS = 5000;

// ✅ 列挙型の値
const ORDER_TYPE = {
NEW_ENTRY: 0,
UPDATE_PLAN: 10,
CANCEL_CONTRACT: 30,
} as const;

3. パスカルケース(PascalCase)

説明: 全ての単語の先頭を大文字にする(アッパーキャメルケースとも言う)

✅ Good: 使用場面: クラス、インターフェース、型エイリアス、列挙型
// ✅ 使用場面: クラス、インターフェース、型エイリアス、列挙型

// クラス
class UserAccount {
private userName: string;

constructor(userName: string) {
this.userName = userName;
}
}

// インターフェース
interface UserProfile {
id: number;
name: string;
email: string;
}

// 型エイリアス
type ApiResult<T> = {
data: T;
status: number;
};

// 列挙型(Enum)
enum OrderStatus {
Pending,
Processing,
Completed,
Cancelled,
}

// React コンポーネント(関数コンポーネント)
function UserProfileCard({ user }: { user: UserProfile }) {
return <div>{user.name}</div>;
}

4. キャメルケース(camelCase)

説明: 先頭の単語は小文字、後に続く単語の先頭を大文字にする。

✅ Good: 使用場面: 変数、関数、メソッド、プロパティ
// ✅ 使用場面: 変数、関数、メソッド、プロパティ

// 変数
const userName = "Taro";
const totalAmount = 1000;
const isAuthenticated = true;

// 関数
function calculateTotalPrice(price: number, quantity: number): number {
return price * quantity;
}

// メソッド
class ShoppingCart {
private items: Item[] = [];

addItem(item: Item): void {
this.items.push(item);
}

getTotalPrice(): number {
return this.items.reduce((sum, item) => sum + item.price, 0);
}
}

// オブジェクトのプロパティ
const userSettings = {
displayName: "Taro Yamada",
emailAddress: "taro@example.com",
notificationEnabled: true,
};

TypeScriptにおける命名規則のまとめ

// ────────────────────────────────────────────
// 📋 TypeScript 命名規則チートシート
// ────────────────────────────────────────────

// 1️⃣ 変数・定数
const userName = "Taro"; // ✅ キャメルケース(通常の変数)
const MAX_RETRY_COUNT = 3; // ✅ アッパースネークケース(定数)

// 2️⃣ 関数
function getUserById(id: number) {} // ✅ キャメルケース

// 3️⃣ クラス
class UserAccount {} // ✅ パスカルケース

// 4️⃣ インターフェース
interface UserProfile {} // ✅ パスカルケース
// インターフェースに "I" プレフィックスは付けない(非推奨)
interface IUserProfile {} // ❌ 古い慣習

// 5️⃣ 型エイリアス
type UserId = string; // ✅ パスカルケース
type UserData = { id: number }; // ✅ パスカルケース

// 6️⃣ Enum(列挙型)
enum UserRole { // ✅ パスカルケース(型名)
Admin, // ✅ パスカルケース(メンバー)
User,
Guest,
}

// 7️⃣ ジェネリック型パラメータ
function identity<T>(value: T): T { return value; } // ✅ 1文字の大文字(T, U, V など)
class Container<TItem> {} // ✅ または T + 説明的な名前

// 8️⃣ プライベートフィールド
class User {
private userName = ""; // ✅ キャメルケース
#password = ""; // ✅ # プレフィックス(ECMAScript private)
}

練習問題 1: 命名規則の適用

以下のコードを正しい命名規則で書き直してみましょう。

❌ Bad: 修正前
// ❌ 修正前
class user_data {
constructor(public user_name: string) {}
}

interface product_info {
product_id: number;
product_name: string;
}

const TAX_RATE = 0.1;
function CALCULATE_PRICE(price: number): number {
return price * (1 + TAX_RATE);
}

enum order_status {
pending = 'PENDING',
completed = 'COMPLETED',
}
📝 解答を見る
✅ Good: 修正後
// ✅ 修正後

// クラスはパスカルケース
class UserData {
constructor(public userName: string) {}
}

// インターフェースはパスカルケース、プロパティはキャメルケース
interface ProductInfo {
productId: number;
productName: string;
}

// 定数はアッパースネークケース
const TAX_RATE = 0.1;

// 関数はキャメルケース
function calculatePrice(price: number): number {
return price * (1 + TAX_RATE);
}

// Enumはパスカルケース
enum OrderStatus {
Pending = 'PENDING',
Completed = 'COMPLETED',
}

※ この問題はケース(大文字・小文字と区切り方)の変換のみを扱っています。UserData という名前自体の良し悪しは、第 3 部の「意味のない単語を含めない」の節を参照してください。


変数の命名規則

原則: 変数は「何を格納しているか」を明確に表す

❌ Bad: 抽象的すぎる
// ❌ Bad: 抽象的すぎる
let number = 20;
let str = "red";
let data = { id: 1 };

// ✅ Good: 具体的で意味が明確
let age = 20;
let themeColor = "red";
let userData = { id: 1 };

型情報を変数名に含めない

TypeScriptでは型システムがあるため、型情報を変数名に含める必要はありません。

❌ Bad: 型情報を名前に含める(ハンガリアン記法)
// ❌ Bad: 型情報を名前に含める(ハンガリアン記法)
const strUserName = "Taro";
const numAge = 25;
const arrItems: number[] = [1, 2, 3];
const objUser = { id: 1 };

// ✅ Good: 型は型アノテーションで表現
const userName: string = "Taro";
const age: number = 25;
const items: number[] = [1, 2, 3];
const user: User = { id: 1 };

// ✅ Better: 型推論を活用(冗長な型アノテーションを避ける)
const userName = "Taro"; // 型推論で string
const age = 25; // 型推論で number
const items = [1, 2, 3]; // 型推論で number[]
const user: User = { id: 1 }; // 型が明示的に必要な場合のみ

真偽値(boolean)の命名規則

真偽値を格納する変数は、その値が truefalse かを表す命名にします。

接頭辞のパターン

真偽値の命名パターン

パターン
is + 名詞 / 形容詞isVisible, isValid
has + 名詞hasError, hasChildren
can + 動詞canEdit, canDelete
should + 動詞shouldUpdate, shouldRetry
過去分詞completed, finished

具体例

✅ Good: is + 形容詞/名詞
// ✅ is + 形容詞/名詞
const isVisible = true;
const isAuthenticated = false;
const isValid = checkValidity();
const isLoading = true;
const isEmpty = array.length === 0;

// ✅ has + 名詞
const hasError = errors.length > 0;
const hasChildren = node.children.length > 0;
const hasPermission = user.role === 'admin';

// ✅ can + 動詞
const canEdit = user.permissions.includes('edit');
const canDelete = user.role === 'admin';
const canSubmit = isValid && !isLoading;

// ✅ should + 動詞
const shouldUpdate = newVersion > currentVersion;
const shouldRetry = attemptCount < MAX_RETRIES;
const shouldShowWarning = diskUsage > 0.9;

// ✅ 過去分詞形
const completed = tasks.every(task => task.status === 'done');
const enabled = settings.featureFlags.newUI;

❌ 避けるべきパターン

❌ Bad: 避けるべきパターン
// ❌ Bad: 否定形は避ける(二重否定で混乱)
const notComplete = false;
if (!notComplete) { // 読みにくい
// ...
}

// ✅ Good: 肯定形を使う
const isComplete = true;
if (isComplete) { // 読みやすい
// ...
}

// ❌ Bad: 動詞だけで真偽値を表すのは避ける
const display = true; // displayは動詞なので関数と混同しやすい

// ✅ Good: is + 過去分詞
const isDisplayed = true;

// ❌ Bad: 型名を使う
const boolean = true;
const string = typeof value === 'string';

// ✅ Good: 具体的な状態を表す
const isEnabled = true;
const isString = typeof value === 'string';

練習問題 2: 真偽値の命名

// 以下の変数名を適切な命名に修正してください

// 1. ユーザーが成人かどうか
const xxx = age >= 18;

// 2. 配列が空かどうか
const xxx = array.length === 0;

// 3. 編集権限があるかどうか
const xxx = user.role === 'admin' || user.role === 'editor';

// 4. ファイルが存在するかどうか
const xxx = fs.existsSync(filePath);

// 5. 全てのタスクが完了したかどうか
const xxx = tasks.every(task => task.done);
📝 解答を見る
✅ Good: 解答
// ✅ 解答

// 1. ユーザーが成人かどうか
const isAdult = age >= 18;
// または
const isOfAge = age >= 18;

// 2. 配列が空かどうか
const isEmpty = array.length === 0;

// 3. 編集権限があるかどうか
const canEdit = user.role === 'admin' || user.role === 'editor';
// または
const hasEditPermission = user.role === 'admin' || user.role === 'editor';

// 4. ファイルが存在するかどうか
const fileExists = fs.existsSync(filePath);
// または
const hasFile = fs.existsSync(filePath);

// 5. 全てのタスクが完了したかどうか
const allCompleted = tasks.every(task => task.done);
// または
const isAllTasksCompleted = tasks.every(task => task.done);

定数の命名規則

定数とは

TypeScriptにおける定数には2つの意味があります:

  1. 再代入できない変数constで宣言)
  2. アプリケーション全体で不変の値(設定値、マジックナンバーの代替など)
// ────────────────────────────────────────────
// const の2つの意味を理解する
// ────────────────────────────────────────────

// 1️⃣ 再代入できない変数(通常のconst)
const user = { name: "Taro" };
user.name = "Hanako"; // ✅ プロパティの変更は可能
// user = {}; // ❌ 再代入は不可

// 2️⃣ 完全に不変の値(アプリケーション定数)
const MAX_RETRY_COUNT = 3; // ✅ アッパースネークケース
const API_BASE_URL = "https://api.example.com";

命名規則の使い分け

✅ Good: 環境変数、設定値
// ────────────────────────────────────────────
// アッパースネークケース(UPPER_SNAKE_CASE)
// ────────────────────────────────────────────
// 用途: アプリケーション全体で変更されない値

// ✅ 環境変数、設定値
const API_ENDPOINT = "https://api.example.com";
const DEFAULT_LOCALE = "ja-JP";
const MAX_FILE_SIZE_MB = 10;

// ✅ マジックナンバーの代替
const TAX_RATE = 0.1;
const SECONDS_PER_MINUTE = 60;
const MILLISECONDS_PER_SECOND = 1000;

// ✅ ループの上限値
const MAX_RETRY_ATTEMPTS = 3;
const PAGE_SIZE = 20;

// ✅ 定数オブジェクト(as const を使用)
const HTTP_STATUS = {
OK: 200,
BAD_REQUEST: 400,
UNAUTHORIZED: 401,
NOT_FOUND: 404,
} as const;

const ORDER_TYPE = {
NEW_ENTRY: 0,
UPDATE_PLAN: 10,
CANCEL_CONTRACT: 30,
} as const;

// ────────────────────────────────────────────
// キャメルケース(camelCase)
// ────────────────────────────────────────────
// 用途: 通常の変数(オブジェクトや配列など)

// ✅ オブジェクトインスタンス
const userSettings = {
theme: "dark",
language: "ja",
};

// ✅ 配列
const itemList = [1, 2, 3];

// ✅ クラスインスタンス
const httpClient = new HttpClient();

// ✅ 関数の結果
const calculatedValue = calculateTotal();

as const による型の厳密化

as const を使用することで、値を完全に不変にし、型をリテラル型として扱えます。

❌ Bad: as const なし
// ────────────────────────────────────────────
// as const の効果
// ────────────────────────────────────────────

// ❌ as const なし
const ORDER_TYPE_1 = {
NEW: 0,
UPDATE: 10,
};
// 型: { NEW: number; UPDATE: number }
// ORDER_TYPE_1.NEW の型は number(広すぎる)

// ✅ as const あり
const ORDER_TYPE_2 = {
NEW: 0,
UPDATE: 10,
} as const;
// 型: { readonly NEW: 0; readonly UPDATE: 10 }
// ORDER_TYPE_2.NEW の型は 0(リテラル型で厳密)

// ✅ 実用例: 型安全な定数オブジェクト
const USER_ROLE = {
ADMIN: 'admin',
USER: 'user',
GUEST: 'guest',
} as const;

// 型を抽出
type UserRole = typeof USER_ROLE[keyof typeof USER_ROLE];
// 型: "admin" | "user" | "guest"

function checkPermission(role: UserRole) {
if (role === USER_ROLE.ADMIN) {
// ...
}
}

checkPermission(USER_ROLE.ADMIN); // ✅ OK
checkPermission('admin'); // ✅ OK
// checkPermission('superuser'); // ❌ エラー

練習問題 3: 定数の命名

// 以下の定数を適切に命名してください

// 1. 消費税率(10%)
const xxx = 0.1;

// 2. 最大ログイン試行回数
const xxx = 5;

// 3. ユーザー情報(オブジェクト)
const xxx = {
id: 1,
name: "Taro"
};

// 4. エラーコード一覧
const xxx = {
notFound: 404,
serverError: 500,
};

// 5. 曜日の配列
const xxx = ["日", "月", "火", "水", "木", "金", "土"];
📝 解答を見る
✅ Good: 解答
// ✅ 解答

// 1. 消費税率(10%) - 変更されない値なのでアッパースネークケース
const TAX_RATE = 0.1;

// 2. 最大ログイン試行回数 - 設定値なのでアッパースネークケース
const MAX_LOGIN_ATTEMPTS = 5;

// 3. ユーザー情報(オブジェクト) - インスタンスなのでキャメルケース
const currentUser = {
id: 1,
name: "Taro"
};

// 4. エラーコード一覧 - 定数オブジェクトなのでアッパースネークケース + as const
const ERROR_CODE = {
NOT_FOUND: 404,
SERVER_ERROR: 500,
} as const;

// 5. 曜日の配列 - 変更されないリストなので両方あり得る
const DAYS_OF_WEEK = ["日", "月", "火", "水", "木", "金", "土"] as const;
// または用途に応じて
const daysOfWeek = ["日", "月", "火", "水", "木", "金", "土"];

次に読む