mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-31 09:37:15 +01:00
- ✨ **Feature**: Added InputControlDirective for better input handling - 🎨 **Style**: Updated button and text-field styles for loading states - 🛠️ **Refactor**: Improved button component structure and disabled state handling - 📚 **Docs**: Updated code style guidelines with new control flow syntax
223 lines
5.8 KiB
Markdown
223 lines
5.8 KiB
Markdown
# 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<IUser> => {
|
|
// ...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 = <T extends IUserProps>(id: string): Promise<T> => {
|
|
// ...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#)
|