TypeScript Development Rules (Frontend)
Basic Principles
✅ Aggressive Refactoring - Prevent technical debt and maintain health ❌ Unused "Just in Case" Code - Violates YAGNI principle (Kent Beck)
Comment Writing Rules
- •Function Description Focus: Describe what the code "does"
- •No Historical Information: Do not record development history
- •Timeless: Write only content that remains valid whenever read
- •Conciseness: Keep explanations to necessary minimum
Type Safety
Absolute Rule: any type is completely prohibited. It disables type checking and becomes a source of runtime errors.
any Type Alternatives (Priority Order)
- •unknown Type + Type Guards: Use for validating external input (API responses, localStorage, URL parameters)
- •Generics: When type flexibility is needed
- •Union Types・Intersection Types: Combinations of multiple types
- •Type Assertions (Last Resort): Only when type is certain
Type Guard Implementation Pattern
function isUser(value: unknown): value is User {
return (
typeof value === 'object' &&
value !== null &&
'id' in value &&
'name' in value
);
}
Modern Type Features
- •satisfies Operator:
const config = { apiUrl: '/api' } satisfies Config- Preserves inference - •const Assertion:
const ROUTES = { HOME: '/' } as const satisfies Routes- Immutable and type-safe - •Branded Types:
type UserId = string & { __brand: 'UserId' }- Distinguish meaning - •Template Literal Types:
type EventName = \on${Capitalize<string>}`` - Express string patterns with types
Type Safety in Frontend Implementation
- •React Props/State: TypeScript manages types, unknown unnecessary
- •External API Responses: Always receive as
unknown, validate with type guards - •localStorage/sessionStorage: Treat as
unknown, validate - •URL Parameters: Treat as
unknown, validate - •Form Input (Controlled Components): Type-safe with React synthetic events
Type Safety in Data Flow
- •Frontend → Backend: Props/State (Type Guaranteed) → API Request (Serialization)
- •Backend → Frontend: API Response (
unknown) → Type Guard → State (Type Guaranteed)
Type Complexity Management
- •Props Design:
- •Props count: 3-7 props ideal (consider component splitting if exceeds 10)
- •Optional Props: 50% or less (consider default values or Context if excessive)
- •Nesting: Up to 2 levels (flatten deeper structures)
- •Type Assertions: Review design if used 3+ times
- •External API Types: Relax constraints and define according to reality (convert appropriately internally)
Coding Conventions
Component Design Criteria
- •Function Components (Mandatory): Official React recommendation, optimizable by modern tooling
- •Classes Prohibited: Class components completely deprecated (Exception: Error Boundary)
- •Custom Hooks: Standard pattern for logic reuse and dependency injection
- •Component Hierarchy: Atoms → Molecules → Organisms → Templates → Pages
- •Co-location: Place tests, styles, and related files alongside components
State Management Patterns
- •Local State:
useStatefor component-specific state - •Context API: For sharing state across component tree (theme, auth, etc.)
- •Custom Hooks: Encapsulate state logic and side effects
- •Server State: React Query or SWR for API data caching
Data Flow Principles
- •Single Source of Truth: Each piece of state has one authoritative source
- •Unidirectional Flow: Data flows top-down via props
- •Immutable Updates: Use immutable patterns for state updates
// ✅ Immutable state update setUsers((prev) => [...prev, newUser]); // ❌ Mutable state update users.push(newUser); setUsers(users);
Function Design
- •0-2 parameters maximum: Use object for 3+ parameters
typescript
// ✅ Object parameter function createUser({ name, email, role }: CreateUserParams) {}
Props Design (Props-driven Approach)
- •Props are the interface: Define all necessary information as props
- •Avoid implicit dependencies: Do not depend on global state or context without necessity
- •Type-safe: Always define Props type explicitly
Environment Variables
- •Use build tool's environment variable system:
process.envdoes not work in browsers - •Centrally manage environment variables through configuration layer
- •Implement proper type safety and default value handling
// ✅ Build tool environment variables (public values only)
const config = {
apiUrl: import.meta.env.API_URL || 'http://localhost:3000',
appName: import.meta.env.APP_NAME || 'My App',
};
// ❌ Does not work in frontend
const apiUrl = process.env.API_URL;
Security (Client-side Constraints)
- •CRITICAL: All frontend code is public and visible in browser
- •Never store secrets client-side: No API keys, tokens, or secrets in environment variables
- •Do not include
.envfiles in Git - •Do not include sensitive information in error messages
// ❌ Security risk: API key exposed in browser
const apiKey = import.meta.env.API_KEY;
const response = await fetch(`https://api.example.com/data?key=${apiKey}`);
// ✅ Correct: Backend manages secrets, frontend accesses via proxy
const response = await fetch('/api/data'); // Backend handles API key authentication
Dependency Injection
- •Custom Hooks for dependency injection: Ensure testability and modularity
Asynchronous Processing
- •Promise Handling: Always use
async/await - •Error Handling: Always handle with
try-catchor Error Boundary - •Type Definition: Explicitly define return value types (e.g.,
Promise<Result>)
Format Rules
- •Semicolon omission (follow Biome settings)
- •Types in
PascalCase, variables/functions incamelCase - •Imports use absolute paths (
src/)
Clean Code Principles
- •✅ Delete unused code immediately
- •✅ Delete debug
console.log() - •❌ Commented-out code (manage history with version control)
- •✅ Comments explain "why" (not "what")
Error Handling
Absolute Rule: Error suppression prohibited. All errors must have log output and appropriate handling.
Fail-Fast Principle: Fail quickly on errors to prevent continued processing in invalid states
// ❌ Prohibited: Unconditional fallback
catch (error) {
return defaultValue // Hides error
}
// ✅ Required: Explicit failure
catch (error) {
logger.error('Processing failed', error)
throw error // Handle with Error Boundary or higher layer
}
Result Type Pattern: Express errors with types for explicit handling
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
// Example: Express error possibility with types
function parseUser(data: unknown): Result<User, ValidationError> {
if (!isValid(data)) return { ok: false, error: new ValidationError() };
return { ok: true, value: data as User };
}
Custom Error Classes
export class AppError extends Error {
constructor(
message: string,
public readonly code: string,
public readonly statusCode = 500
) {
super(message);
this.name = this.constructor.name;
}
}
// Purpose-specific: ValidationError(400), ApiError(502), NotFoundError(404)
Layer-Specific Error Handling (React)
- •Error Boundary: Catch React component errors, display fallback UI
- •Custom Hook: Detect business rule violations, propagate AppError as-is
- •API Layer: Convert fetch errors to domain errors
Structured Logging and Sensitive Information Protection Never include sensitive information (password, token, apiKey, secret, creditCard) in logs
Asynchronous Error Handling in React
- •Error Boundary setup mandatory: Catch rendering errors
- •Use try-catch with all async/await in event handlers
- •Always log and re-throw errors or display error state
Refactoring Techniques
Basic Policy
- •Small Steps: Maintain always-working state through gradual improvements
- •Safe Changes: Minimize the scope of changes at once
- •Behavior Guarantee: Ensure existing behavior remains unchanged while proceeding
Implementation Procedure: Understand Current State → Gradual Changes → Behavior Verification → Final Validation
Priority: Duplicate Code Removal > Large Function Division > Complex Conditional Branch Simplification > Type Safety Improvement
Performance Optimization
- •Component Memoization: Use React.memo for expensive components
- •State Optimization: Minimize re-renders with proper state structure
- •Lazy Loading: Use React.lazy and Suspense for code splitting
- •Bundle Size: Monitor with the
buildscript and keep under 500KB
Non-functional Requirements
- •Browser Compatibility: Chrome/Firefox/Safari/Edge (latest 2 versions)
- •Rendering Time: Within 5 seconds for major pages