コンテンツにスキップ

コーディング規約

フォーマット

Biome設定

  • インデント: スペース4つ

  • 行幅: 120文字

  • セミコロン: 必須

  • クォート: ダブルクォート(JSX含む)

  • 末尾カンマ: あり(JavaScript/TypeScript)

  • アロー関数の括弧: 常に使用

コードスタイル

// ✅ Good: セミコロンあり、末尾カンマあり
const items = [
"item1",
"item2",
];
// ✅ Good: アロー関数に括弧を使用
const handleClick = () => {
// ...
};
// ✅ Good: ダブルクォートを使用
const message = "Hello, world!";

命名規則

コンポーネント

  • PascalCaseを使用

  • ファイル名はコンポーネント名と一致させる

// ✅ Good
export const BlogPreview = () => {
// ...
};
// ファイル名: BlogPreview.tsx

変数・関数

  • camelCaseを使用

  • 関数は動詞で始める(handle, get, set / is, has など)

// ✅ Good
const userName = "John";
const handleSubmit = () => {};
const getUserData = () => {};
const isVisible = true;
const hasPermission = false;

定数

  • UPPER_SNAKE_CASEを使用

  • shared/config/constants.tsに集約

// ✅ Good
export const SITE_TITLE = "Portfolio";
export const SOCIAL_GITHUB = "https://github.com/...";

型・インターフェース

  • PascalCaseを使用

  • インターフェースはPropsサフィックスを付ける

// ✅ Good
export interface BlogPreviewProps {
title: string;
date: string;
}
export type UserRole = "admin" | "user";

インポート順序

  1. 外部ライブラリ(React、Remixなど)
  2. 内部モジュール(~/shared, ~/featuresなど)
  3. 相対インポート
  4. 型インポート(typeキーワードを使用)
// ✅ Good
import { Link } from "@remix-run/react";
import classnames from "classnames";
import { BlogPreview } from "~/features/blog-preview";
import { Button } from "@portfolio/ui";
import type { BlogPreviewProps } from "~/features/blog-preview";

TypeScript

型定義

  • 厳格モードを有効化
  • anyの使用を避ける
  • 型推論を活用するが、明示的な型も適切に使用
// ✅ Good: 型推論を活用
const count = 0; // number
// ✅ Good: 明示的な型が必要な場合
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
// ...
};
// ❌ Bad: anyの使用
const data: any = fetchData();

Props型定義

  • コンポーネントファイル内で定義
  • exportして再利用可能にする
// ✅ Good
export interface BlogPreviewProps {
title: string;
date: string;
className?: string;
}
export const BlogPreview = (props: BlogPreviewProps) => {
// ...
};

コメント

  • 複雑なロジックには説明コメントを追加
  • JSDocコメントは公開APIに使用
// ✅ Good: 複雑なロジックの説明
// 日付をUTCタイムゾーンでフォーマットし、ローカルタイムゾーンに変換
const dateString = created.toLocaleDateString("en-US", {
day: "2-digit",
month: "2-digit",
timeZone: "UTC",
year: "numeric",
});
/**
* ブログ記事のプレビューを表示するコンポーネント
* @param props - BlogPreviewProps
*/
export const BlogPreview = (props: BlogPreviewProps) => {
// ...
};

ファイル構造

コンポーネントファイル

// 1. インポート
import { Link } from "@remix-run/react";
// 2. 型定義
export interface ComponentProps {
// ...
}
// 3. コンポーネント実装
export const Component = (props: ComponentProps) => {
// ...
};
// 4. デフォルトエクスポート(必要な場合のみ)
export default Component;