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

命名規則

なぜ変数名が大切なのか

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

❌ 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 {} // ✅ 1文字の大文字(T, U, V など)
class Container<TItem> {} // ✅ または T + 説明的な名前

// 8️⃣ プライベートフィールド
class User {
private userName: string; // ✅ キャメルケース
#password: string; // ✅ # プレフィックス(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',
}

変数の命名規則

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

❌ 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 >= 20;

// 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 >= 20;
// または
const isOfAge = age >= 20;

// 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 DAY_OF_WEEK = ["日", "月", "火", "水", "木", "金", "土"] as const;
// または用途に応じて
const dayOfWeek = ["日", "月", "火", "水", "木", "金", "土"];

関数の命名規則

関数名は「何をするのか」を明確に表す動詞で始めます。

基本パターン

関数名のパターン

パターン
get + 名詞getUserById, getCurrentTime
set + 名詞setUserName, setTheme
calculate + 名詞calculateTotal, calculateAge
fetch + 名詞fetchUserData, fetchPosts
create + 名詞createUser, createElement
update + 名詞updateProfile, updateSettings
delete + 名詞deleteUser, removeItem
validate + 名詞validateEmail, validateInput
convert + A + to + BconvertMinsToHours

具体例

✅ Good: 動作が明確な関数名
// ✅ Good: 動作が明確な関数名

// get系: データの取得(副作用なし)
function getUserById(id: number): User | undefined {
return users.find(user => user.id === id);
}

function getCurrentTime(): Date {
return new Date();
}

function getFullName(firstName: string, lastName: string): string {
return `${firstName} ${lastName}`;
}

// set系: 値の設定(副作用あり)
function setTheme(theme: 'light' | 'dark'): void {
document.body.className = theme;
}

// calculate系: 計算処理
function calculateTotalPrice(items: Item[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}

function calculateAge(birthDate: Date): number {
const today = new Date();
return today.getFullYear() - birthDate.getFullYear();
}

// fetch系: 非同期データ取得
async function fetchUserData(userId: string): Promise<User> {
const response = await fetch(`/api/users/${userId}`);
return response.json();
}

// create系: 新規作成
function createUser(name: string, email: string): User {
return {
id: generateId(),
name,
email,
createdAt: new Date(),
};
}

// update系: 更新
function updateUserProfile(userId: string, updates: Partial<User>): void {
const user = getUserById(userId);
if (user) {
Object.assign(user, updates);
}
}

// delete/remove系: 削除
function deleteUser(userId: string): boolean {
const index = users.findIndex(u => u.id === userId);
if (index !== -1) {
users.splice(index, 1);
return true;
}
return false;
}

// validate系: 検証
function validateEmail(email: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}

// convert系: 変換
function convertMinsToHours(minutes: number): number {
return minutes / 60;
}

function convertCelsiusToFahrenheit(celsius: number): number {
return (celsius * 9/5) + 32;
}

❌ 避けるべきパターン

❌ Bad: 避けるべきパターン
// ❌ Bad: 抽象的すぎる
function process(data: any) {
// 何を処理するのか不明
}

function handle(value: string) {
// 何を扱うのか不明
}

function doSomething() {
// 何をするのか不明
}

// ✅ Good: 具体的
function processPayment(payment: Payment) {
// 支払い処理をすることが明確
}

function handleUserInput(input: string) {
// ユーザー入力を扱うことが明確
}

function sendEmailNotification() {
// メール通知を送信することが明確
}

// ❌ Bad: 単語の省略
function calc(num: number): number {
return num * 2;
}

function getUserInf(id: number) {
// ...
}

// ✅ Good: 完全な単語
function calculate(num: number): number {
return num * 2;
}

function getUserInfo(id: number) {
// ...
}

真偽値を返す関数の命名規則

真偽値を返す関数は、疑問文(Yes/Noで答えられる形)になるように命名します。

✅ Good: is + 形容詞/名詞
// ────────────────────────────────────────────
// 真偽値を返す関数の命名パターン
// ────────────────────────────────────────────

// ✅ is + 形容詞/名詞
function isValid(value: string): boolean {
return value.length > 0;
}

function isAdult(age: number): boolean {
return age >= 20;
}

function isEmpty(array: any[]): boolean {
return array.length === 0;
}

// ✅ has + 名詞
function hasPermission(user: User, permission: string): boolean {
return user.permissions.includes(permission);
}

function hasError(result: Result): boolean {
return result.errors.length > 0;
}

// ✅ can + 動詞
function canEdit(user: User, document: Document): boolean {
return user.id === document.authorId || user.role === 'admin';
}

function canSubmit(form: Form): boolean {
return form.isValid && !form.isSubmitting;
}

// ✅ should + 動詞
function shouldRetry(attempt: number, maxAttempts: number): boolean {
return attempt < maxAttempts;
}

function shouldShowWarning(value: number, threshold: number): boolean {
return value > threshold;
}

// ✅ exists(存在チェック)
function exists(path: string): boolean {
return fs.existsSync(path);
}

// ❌ Bad: 動詞始まりで真偽値を返す(アクションと混同)
function checkValid(value: string): boolean { // check は動作に見える
return value.length > 0;
}

// ✅ Good
function isValid(value: string): boolean {
return value.length > 0;
}

練習問題 4: 関数の命名

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

// 1. ユーザー全員を取得する関数
async function xxx() {
const response = await fetch('/api/users');
return response.json();
}

// 2. 偶数かどうかを判定する関数
function xxx(num: number): boolean {
return num % 2 === 0;
}

// 3. 配列の最大値を取得する関数
function xxx(numbers: number[]): number {
return Math.max(...numbers);
}

// 4. ファイルが存在するか確認する関数
function xxx(filePath: string): boolean {
return fs.existsSync(filePath);
}

// 5. 価格に消費税を加算する関数
function xxx(price: number, taxRate: number): number {
return price * (1 + taxRate);
}
📝 解答を見る
✅ Good: 解答
// ✅ 解答

// 1. ユーザー全員を取得する関数
async function getAllUsers(): Promise<User[]> {
const response = await fetch('/api/users');
return response.json();
}
// または
async function fetchAllUsers(): Promise<User[]> {
const response = await fetch('/api/users');
return response.json();
}

// 2. 偶数かどうかを判定する関数
function isEven(num: number): boolean {
return num % 2 === 0;
}

// 3. 配列の最大値を取得する関数
function getMaxValue(numbers: number[]): number {
return Math.max(...numbers);
}
// または
function findMaxValue(numbers: number[]): number {
return Math.max(...numbers);
}

// 4. ファイルが存在するか確認する関数
function fileExists(filePath: string): boolean {
return fs.existsSync(filePath);
}
// または
function hasFile(filePath: string): boolean {
return fs.existsSync(filePath);
}

// 5. 価格に消費税を加算する関数
function calculatePriceWithTax(price: number, taxRate: number): number {
return price * (1 + taxRate);
}
// または
function addTaxToPrice(price: number, taxRate: number): number {
return price * (1 + taxRate);
}

クラスの命名規則

クラスは名詞で命名します。そのクラスが表すもの・概念を明確に示す名前を選びます。

✅ Good: 名詞で表現
// ────────────────────────────────────────────
// クラスの命名パターン
// ────────────────────────────────────────────

// ✅ Good: 名詞で表現

// エンティティ(モデル)
class User {
constructor(
public id: string,
public name: string,
public email: string
) {}
}

class Product {
constructor(
public id: string,
public name: string,
public price: number
) {}
}

// サービス(責務を表す名詞)
class UserService {
createUser(name: string, email: string): User {
return new User(generateId(), name, email);
}

deleteUser(userId: string): void {
// ...
}
}

class EmailNotificationService {
send(to: string, subject: string, body: string): void {
// ...
}
}

// ユーティリティ
class DateFormatter {
format(date: Date, format: string): string {
// ...
}
}

class StringValidator {
isEmail(value: string): boolean {
// ...
}

isUrl(value: string): boolean {
// ...
}
}

// マネージャー(管理を表すクラス)
class SessionManager {
private sessions: Map<string, Session> = new Map();

create(userId: string): Session {
// ...
}

destroy(sessionId: string): void {
// ...
}
}

// コントローラー(React/Angularなど)
class UserController {
getUser(req: Request, res: Response): void {
// ...
}
}

// ❌ Bad: 動詞で始まる
class CalculatePrice { // 動詞
// ...
}

class GetUser { // 動詞
// ...
}

// ✅ Good: 名詞に修正
class PriceCalculator {
calculate(items: Item[]): number {
// ...
}
}

class UserRepository {
getById(id: string): User | undefined {
// ...
}
}

クラス名のサフィックスパターン

一般的なサフィックス(接尾辞)を使うことで、クラスの役割を明確にできます。

// ────────────────────────────────────────────
// 一般的なクラスのサフィックス
// ────────────────────────────────────────────

// 🔹 ~Service: ビジネスロジックを提供
class AuthenticationService {
login(email: string, password: string): Promise<User> { }
logout(): void { }
}

// 🔹 ~Repository: データアクセス層
class UserRepository {
findById(id: string): Promise<User | null> { }
save(user: User): Promise<void> { }
}

// 🔹 ~Controller: リクエスト処理
class UserController {
getUser(req: Request, res: Response): void { }
createUser(req: Request, res: Response): void { }
}

// 🔹 ~Manager: リソース管理
class ConnectionManager {
open(): Connection { }
close(connection: Connection): void { }
}

// 🔹 ~Factory: オブジェクト生成
class UserFactory {
create(data: UserData): User {
return new User(data);
}
}

// 🔹 ~Builder: 複雑なオブジェクトの段階的構築
class QueryBuilder {
private query = '';

select(fields: string[]): this {
this.query += `SELECT ${fields.join(', ')} `;
return this;
}

from(table: string): this {
this.query += `FROM ${table} `;
return this;
}

build(): string {
return this.query;
}
}

// 🔹 ~Validator: 検証
class FormValidator {
validate(data: FormData): ValidationResult {
// ...
}
}

// 🔹 ~Helper / ~Util: ユーティリティ
class DateHelper {
formatDate(date: Date): string { }
parseDate(str: string): Date { }
}

// 🔹 ~Handler: イベント・エラー処理
class ErrorHandler {
handle(error: Error): void {
console.error(error);
}
}

メソッド名は冗長にしない

クラスのメソッドは、すでにクラス名で文脈が明確なので、クラス名を繰り返す必要はありません。

❌ Bad: クラス名を繰り返している
// ❌ Bad: クラス名を繰り返している
class User {
printUserProfile(): void {
console.log(this.name);
}

getUserEmail(): string {
return this.email;
}
}

// ✅ Good: 簡潔で明確
class User {
printProfile(): void {
console.log(this.name);
}

getEmail(): string {
return this.email;
}
}

// 使用時には文脈が明確
const user = new User("Taro", "taro@example.com");
user.printProfile(); // ✅ Userのprofileを表示することは自明
user.getEmail(); // ✅ Userのemailを取得することは自明

より多くの例

❌ Bad
// ❌ Bad
class Product {
getProductName(): string { }
setProductPrice(price: number): void { }
calculateProductDiscount(): number { }
}

// ✅ Good
class Product {
getName(): string { }
setPrice(price: number): void { }
calculateDiscount(): number { }
}

// ❌ Bad
class ShoppingCart {
addItemToShoppingCart(item: Item): void { }
removeItemFromShoppingCart(itemId: string): void { }
getShoppingCartTotal(): number { }
}

// ✅ Good
class ShoppingCart {
addItem(item: Item): void { }
removeItem(itemId: string): void { }
getTotal(): number { }
}

発音可能で意味のある名前を使う

❌ Bad: 省略形、発音不可能
// ❌ Bad: 省略形、発音不可能
const genYmdhms = (): string => {
const now = new Date();
return `${now.getFullYear()}${now.getMonth()}${now.getDate()}`;
};

const dfColor = "#fff";
const usrCnt = 10;

// ✅ Good: 発音可能で意味が明確
const generateTimestamp = (): string => {
const now = new Date();
return `${now.getFullYear()}${now.getMonth()}${now.getDate()}`;
};

const defaultColor = "#fff";
const userCount = 10;

理由:

  • チームメンバーとの口頭でのコミュニケーションが容易
  • コードレビューで説明しやすい
  • 新しいメンバーが理解しやすい

配列・リストには複数形をつける

配列やリストを表す変数には、複数形の s をつけることで一目で配列だと分かります。

❌ Bad: 単数形
// ❌ Bad: 単数形
const user = [{ id: 1 }, { id: 2 }];
const item = ["apple", "banana", "orange"];

user.forEach(u => console.log(u)); // user が配列なのか分かりにくい

// ✅ Good: 複数形
const users = [{ id: 1 }, { id: 2 }];
const items = ["apple", "banana", "orange"];

users.forEach(user => console.log(user)); // users が配列で user が要素だと明確

// ✅ 他の命名パターン
const userList = [{ id: 1 }, { id: 2 }];
const userArray = [{ id: 1 }, { id: 2 }];
const itemCollection = ["apple", "banana"];

// ✅ TypeScriptの型定義でも複数形を使う
type User = {
id: number;
name: string;
};

type Users = User[]; // または
type UserList = User[];

不規則な複数形

✅ Good: 英語の不規則な複数形
// ✅ 英語の不規則な複数形
const children = [child1, child2]; // child → children
const people = [person1, person2]; // person → people
const mice = [mouse1, mouse2]; // mouse → mice

// ✅ 単複同形
const sheep = [sheep1, sheep2]; // sheep → sheep
const fish = [fish1, fish2]; // fish → fish

同じ意味の単語は統一する

プロジェクト内で同じ概念を表す単語は統一します。

❌ Bad: 同じ概念に異なる単語を使用
// ❌ Bad: 同じ概念に異なる単語を使用
class UserController {
getUser(id: string): User { }
}

class ProductController {
fetchProduct(id: string): Product { } // ❌ get と fetch が混在
}

class OrderController {
retrieveOrder(id: string): Order { } // ❌ retrieve も混在
}

// ✅ Good: 統一
class UserController {
getUser(id: string): User { }
}

class ProductController {
getProduct(id: string): Product { }
}

class OrderController {
getOrder(id: string): Order { }
}

// ────────────────────────────────────────────
// その他の統一例
// ────────────────────────────────────────────

// ❌ Bad: 削除に複数の単語
function removeUser(id: string) { }
function deleteProduct(id: string) { }
function eraseOrder(id: string) { }

// ✅ Good: delete で統一
function deleteUser(id: string) { }
function deleteProduct(id: string) { }
function deleteOrder(id: string) { }

よくある類似語

統一すべき類似語の例

意味候補
取得get / fetch / retrieve
削除delete / remove / erase
作成create / make / build
更新update / modify / edit
送信send / submit / post
表示show / display / render

推奨アプローチ: プロジェクトで**用語集(Glossary)**を作成し、チーム全体で共有しましょう。

✅ Good: プロジェクトの用語統一例(glossary.ts)
// ✅ プロジェクトの用語統一例(glossary.ts)
/**
* プロジェクト用語集
*
* - データ取得: get(非同期の場合は fetch)
* - データ作成: create
* - データ更新: update
* - データ削除: delete
* - 表示: show
*/

対比語を使う

反対の意味を持つ値には、対比のある名前をつけます。

✅ Good: 対比語の例
// ✅ 対比語の例

// 開始 ⇔ 終了
const startTime = new Date();
const endTime = new Date();

function startTimer() { }
function stopTimer() { } // ✅ start ⇔ stop

// 最小 ⇔ 最大
const minValue = 0;
const maxValue = 100;

// 前 ⇔ 次
const previousPage = 1;
const nextPage = 3;

// 最初 ⇔ 最後
const firstItem = items[0];
const lastItem = items[items.length - 1];

// 開く ⇔ 閉じる
function openModal() { }
function closeModal() { } // ✅ open ⇔ close

// 表示 ⇔ 非表示
function showElement() { }
function hideElement() { } // ✅ show ⇔ hide

// 有効 ⇔ 無効
function enableFeature() { }
function disableFeature() { } // ✅ enable ⇔ disable

// ❌ Bad: 対比が不明確
function startProcess() { }
function endProcess() { } // ❌ start ⇔ end は対ではない

// ✅ Good
function startProcess() { }
function stopProcess() { } // ✅ start ⇔ stop

よくある対比語

対比語の一覧

開始 / 動作反対
startstop(終了)
beginend(終わり)
openclose(閉じる)
showhide(隠す)
enabledisable(無効化)
activatedeactivate(非活性)
lockunlock(解除)
firstlast(最後)
minmax(最大)
previousnext(次)
incrementdecrement(減少)
addremove(削除)
insertdelete(削除)
pushpop(取り出し)
acquirerelease(解放)

意味のない単語を含めない

Data, Info, Manager などの汎用的な単語は、具体的な情報を提供しません。可能な限り避けましょう。

❌ Bad: 意味のない単語
// ❌ Bad: 意味のない単語

// "Data" は冗長
class UserData {
name: string;
email: string;
}
// → ユーザーは当然データなので "Data" は不要

// "Info" も冗長
function getUserInfo(id: string) {
// ...
}
// → 情報を取得するのは当然

// ✅ Good: 簡潔で明確
class User {
name: string;
email: string;
}

function getUser(id: string): User {
// ...
}

// ────────────────────────────────────────────

// ❌ Bad: Manager は抽象的すぎる
class DataManager {
processData() { }
}

// ✅ Good: 具体的な責務を示す
class UserRepository {
findById(id: string): User | null { }
save(user: User): void { }
}

// ────────────────────────────────────────────

// ❌ Bad: Object, Thing など抽象的
const userObject = { name: "Taro" };
const dataThing = [1, 2, 3];

// ✅ Good
const user = { name: "Taro" };
const numbers = [1, 2, 3];

ただし例外もある

一部の単語は、特定の文脈で意味を持つ場合があります。

✅ Good: 許容される例
// ✅ 許容される例

// Metadata: 「データに関するデータ」という特定の意味
interface FileMetadata {
size: number;
createdAt: Date;
mimeType: string;
}

// Config/Settings: 設定を表す慣習的な名前
interface AppConfig {
apiUrl: string;
timeout: number;
}

// Context: React/Angularなどのフレームワークの慣習
const UserContext = React.createContext<User | null>(null);

変数名の省略

省略は一般的に認知されている場合のみ使用します。

✅ Good: 一般的に認知されている省略形
// ────────────────────────────────────────────
// ✅ 一般的に認知されている省略形
// ────────────────────────────────────────────

// ID(identifier)
const userId = "12345";
const productId = 100;

// URL(Uniform Resource Locator)
const apiUrl = "https://api.example.com";

// HTTP(HyperText Transfer Protocol)
const httpClient = new HttpClient();

// API(Application Programming Interface)
const apiResponse = await fetchData();

// DB(Database)
const dbConnection = createConnection();

// Auth(Authentication)
const authToken = "abc123";

// Config(Configuration)
const appConfig = loadConfig();

// Temp(Temporary)
const tempValue = calculateTemp();

// Max/Min(Maximum/Minimum)
const maxRetries = 3;
const minValue = 0;

// Prev/Next(Previous/Next)
const prevPage = 1;
const nextPage = 3;

// ────────────────────────────────────────────
// ❌ 避けるべき省略形
// ────────────────────────────────────────────

// ❌ 独自の省略
const usrNm = "Taro"; // ✅ userName
const prdLst = []; // ✅ productList
const calcTtl = () => {}; // ✅ calculateTotal

// ❌ 母音を削除しただけ
const btn = document.querySelector('button'); // ✅ button
const msg = "Hello"; // ✅ message
const err = new Error(); // ✅ error (errは許容される場合も)

// ❌ 文脈なしでは分からない省略
const d = new Date(); // ✅ date または currentDate
const i = 0; // ✅ index または count(ループ以外では)
const tmp = getValue(); // ✅ temporary または具体的な名前

ループ変数の省略は許容される

✅ Good: ループでは慣習的な省略が許容される
// ✅ ループでは慣習的な省略が許容される
for (let i = 0; i < 10; i++) {
console.log(i);
}

// ✅ ネストしたループ
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
matrix[i][j] = 0;
}
}

// ✅ より意味のある名前が望ましい場合
for (let userIndex = 0; userIndex < users.length; userIndex++) {
const user = users[userIndex];
// ...
}

// ✅ forEach/map では完全な名前を使う
users.forEach(user => { // ✅ user (u ではない)
console.log(user.name);
});

練習問題 5: 命名規則の総合問題

以下のコードをクリーンコードの命名規則に従って修正してください。

❌ Bad: 修正前
// ❌ 修正前

const d = new Date();
const usrCnt = 100;

interface prdData {
id: number;
nm: string;
prc: number;
}

class usrMgr {
getUsrInf(id: number) {
// ...
}

delUsr(id: number) {
// ...
}
}

function calcTtl(items: any[]) {
let t = 0;
for (let i = 0; i < items.length; i++) {
t += items[i].prc;
}
return t;
}

const isNotComplete = false;
if (!isNotComplete) {
// ...
}
📝 解答を見る
✅ Good: 修正後
// ✅ 修正後

const currentDate = new Date();
const userCount = 100;

interface ProductData {
id: number;
name: string;
price: number;
}

class UserManager {
getUserInfo(id: number): UserInfo {
// ...
}

deleteUser(id: number): void {
// ...
}
}

function calculateTotal(items: ProductData[]): number {
let total = 0;
for (let i = 0; i < items.length; i++) {
total += items[i].price;
}
return total;
}

// または forEach/reduce を使用
function calculateTotal(items: ProductData[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}

// 否定形を避ける
const isComplete = true;
if (isComplete) {
// ...
}

修正のポイント:

  1. dcurrentDate: 意味を明確に
  2. usrCntuserCount: 省略を避ける
  3. prdDataProductData: パスカルケース
  4. nmname, prcprice: 完全な単語
  5. usrMgrUserManager: パスカルケース
  6. getUsrInfgetUserInfo: 完全な単語
  7. delUsrdeleteUser: 完全な単語 + 動詞で統一
  8. calcTtlcalculateTotal: 完全な単語
  9. ttotal: 意味のある名前
  10. isNotCompleteisComplete: 否定形を避ける

命名規則のまとめ

命名規則クイックリファレンス

対象ルール
変数キャメルケースuserName, itemCount
定数アッパースネークケースMAX_COUNT
関数キャメルケースgetUserById
クラスパスカルケースUserService
インターフェースパスカルケースUserProfile
型エイリアスパスカルケースUserId
EnumパスカルケースUserRole
真偽値is / has / can + 名詞isValid
配列複数形users, items
命名の原則
  • 意図が明確な名前を使う
  • 検索可能な名前を使う
  • 一貫性を保つ
  • 読み手の認知負荷を下げる