# Code Style Guidelines ## General Principles - **Readability First**: Write code that is easy to read and understand. - **Consistency**: Follow the same patterns and conventions throughout the codebase. - **Clean Code**: Avoid unnecessary complexity and keep functions small and focused. ## Extended Guidelines for Angular and TypeScript This section extends the core code style principles with Angular-specific and advanced TypeScript best practices to ensure consistency and maintainability in our projects. ### Angular Enhancements - **Change Detection**: Use the OnPush strategy by default for better performance. - **Lifecycle Hooks**: Explicitly implement Angular lifecycle interfaces. - **Template Management**: Keep templates concise and use the async pipe to handle observables. - **Component Structure**: Follow best practices for component modularization to enhance readability and testability. ### TypeScript Enhancements - **Strict Type Checking**: Enable strict mode (`strict: true`) and avoid excessive use of `any`. - **Interfaces vs. Types**: Prefer interfaces for object definitions and use type aliases for unions and intersections. - **Generics**: Use meaningful type parameter names and constrain generics when applicable. - **Documentation**: Employ JSDoc comments functions and generic parameters to improve code clarity. ## TypeScript Guidelines - **Strict Typing**: - Enable `strict: true` in tsconfig.json - Avoid `any` unless absolutely necessary - Use `unknown` instead of `any` when type is truly unknown - Always specify return types for functions - Use type inference for variable declarations where types are obvious ```typescript // Good const user: User = getUserById('123'); const items = ['apple', 'banana']; // Type inference is fine here // Bad const user: any = getUserById('123'); const items: string[] = ['apple', 'banana']; // Unnecessary type annotation ``` - **Interfaces and Types**: - Prefer `interface` over `type` for object definitions - Use `type` for unions, intersections, and mapped types - Follow Angular's naming convention: `IComponentProps` for props interfaces - Extend interfaces instead of repeating properties - Use readonly modifiers where appropriate ```typescript // Good interface IBaseProps { readonly id: string; name: string; } interface IUserProps extends IBaseProps { email: string; } type ValidationResult = 'success' | 'error' | 'pending'; // Bad type UserProps = { id: string; name: string; email: string; }; ``` - **Enums and Constants**: - Use `const enum` for better performance - Only use regular `enum` when runtime access is required - Prefer union types for simple string literals - **Functions and Methods**: - Use arrow functions for callbacks and class methods - Explicitly type parameters and return values - Keep functions pure when possible - Use function overloads for complex type scenarios - Document complex functions with JSDoc ```typescript // Good /** * Fetches a user by ID and transforms it to the required format * @param id - The user's unique identifier * @param includeDetails - Whether to include additional user details */ const getUser = (id: string, includeDetails = false): Promise => { // ...implementation }; // Bad function getUser(id) { // ...implementation } ``` - **Generics**: - Use meaningful type parameter names (e.g., `T` for type, `K` for key) - Constrain generic types when possible using `extends` - Document generic parameters using JSDoc Example: ```typescript // Good interface IUserProps { id: string; name: string; } interface IAdminProps extends IUserProps { permissions: string[]; } const enum UserRole { Admin = 'ADMIN', User = 'USER', } const getUser = (id: string): Promise => { // ...implementation }; // Bad type User = { id: any; name: any; }; function getUser(id) { // ...implementation } ``` ## Angular-Specific Guidelines - **Components**: - Use OnPush change detection strategy by default - Implement lifecycle hooks interfaces explicitly - Keep templates small and focused - Use async pipe instead of manual subscription management ```typescript // Good @Component({ selector: 'app-user-list', changeDetection: ChangeDetectionStrategy.OnPush, }) export class UserListComponent implements OnInit, OnDestroy { users$ = this.userService.getUsers().pipe(shareReplay(1)); } // Bad @Component({ selector: 'app-user-list', }) export class UserListComponent { users: User[] = []; subscription: Subscription; ngOnInit() { this.subscription = this.userService.getUsers().subscribe((users) => (this.users = users)); } } ``` - **Templates** - Use new control flow syntax - instead if \*ngIf use the @if syntax ## Project-Specific Preferences - **Frameworks**: Follow best practices for Nx, Hono, and Zod. - **Testing**: Use Jest with Spectator for unit tests and follow the Arrange-Act-Assert pattern. - **File Naming**: Use kebab-case for filenames (e.g., `my-component.ts`). - **Comments**: Use JSDoc for documenting functions, classes, and modules. ## Formatting - **Indentation**: Use 2 spaces for indentation. - **Line Length**: Limit lines to 80 characters where possible. - **Semicolons**: Always use semicolons. - **Quotes**: Use single quotes for strings, except when using template literals. ## Linting and Tools - Use ESLint with the recommended TypeScript and Nx configurations. - Prettier should be used for consistent formatting. ## Example ```typescript // Good Example interface User { id: string; name: string; } const getUser = (id: string): User => { // ...function logic... }; // Bad Example function getUser(id) { // ...function logic... } ``` ## References - [Angular Style Guide](https://angular.dev/style-guide#)