|
| 1 | +--- |
| 2 | +description: 'Guidelines for writing high-quality, maintainable TypeScript code with best practices for logging, error handling, code organization, naming, formatting, and style.' |
| 3 | +applyTo: '**/*.ts, **/*.tsx' |
| 4 | +--- |
| 5 | + |
| 6 | +# TypeScript Development Guidelines |
| 7 | + |
| 8 | +This document provides instructions for generating, reviewing, and maintaining TypeScript code. It is designed to guide Copilot and developers in producing domain-specific, robust, and maintainable code across a variety of TypeScript projects. |
| 9 | + |
| 10 | +## General Instructions |
| 11 | + |
| 12 | +- Use modern TypeScript features and syntax. |
| 13 | +- Prefer explicit types and interfaces for clarity and safety. |
| 14 | +- Organize code into logical modules and folders. |
| 15 | +- Write code that is easy to read, test, and maintain. |
| 16 | + |
| 17 | +## Best Practices |
| 18 | + |
| 19 | +- Use `const` and `let` appropriately; avoid `var`. |
| 20 | +- Prefer arrow functions for callbacks and concise function expressions. |
| 21 | +- Use destructuring for objects and arrays to improve readability. |
| 22 | +- Avoid magic numbers and hardcoded values; use named constants. |
| 23 | +- Keep functions pure and side-effect free when possible. |
| 24 | + |
| 25 | +## Code Standards |
| 26 | + |
| 27 | +### Naming Conventions |
| 28 | + |
| 29 | +- Use `camelCase` for variables, functions, and object properties. |
| 30 | +- Use `PascalCase` for types, interfaces, classes, and enums. |
| 31 | +- Use descriptive names; avoid abbreviations except for well-known acronyms. |
| 32 | +- Prefix boolean variables with `is`, `has`, or `should` (e.g., `isActive`). |
| 33 | + |
| 34 | +### File Organization |
| 35 | + |
| 36 | +- Group related code in folders (e.g., `src/`, `tests/`, `lib/`). |
| 37 | +- Place one class, interface, or component per file when possible. |
| 38 | +- Name files using `kebab-case` (e.g., `user-service.ts`). |
| 39 | +- Keep test files close to the code they test (e.g., `src/foo.ts` and `tests/foo.test.ts`). |
| 40 | + |
| 41 | +### Formatting and Style |
| 42 | + |
| 43 | +- Use 2 spaces for indentation. |
| 44 | +- Limit lines to 120 characters. |
| 45 | +- Use single quotes for strings. |
| 46 | +- Never use semicolons for line termination. |
| 47 | +- Avoid trailing commas in multiline objects and arrays. |
| 48 | +- Avoid spaces at start and end of single line braces. |
| 49 | +- Use ESLint and Prettier for consistent formatting. |
| 50 | + |
| 51 | +## Architecture/Structure |
| 52 | + |
| 53 | +- Separate business logic from API handlers and utility functions. |
| 54 | +- Use interfaces and types to define data structures and function signatures. |
| 55 | +- Organize code by feature or domain when scaling projects. |
| 56 | +- Use dependency injection for testability and flexibility. |
| 57 | + |
| 58 | +## Common Patterns |
| 59 | + |
| 60 | +### Logging |
| 61 | + |
| 62 | +- Use a centralized logging utility or library. |
| 63 | +- Log errors, warnings, and important events with context. |
| 64 | +- Avoid logging sensitive information. |
| 65 | +- Example: |
| 66 | + |
| 67 | + ```typescript |
| 68 | + import {logger} from './utils/logger'; |
| 69 | + |
| 70 | + logger.info('Fetching user data', {userId}); |
| 71 | + logger.error('Failed to fetch user', {error}); |
| 72 | + ``` |
| 73 | + |
| 74 | +### Error Handling |
| 75 | + |
| 76 | +- Use `try/catch` for asynchronous code and error-prone operations. |
| 77 | +- Throw custom error types for domain-specific errors. |
| 78 | +- Always handle errors gracefully and provide meaningful messages. |
| 79 | +- Example: |
| 80 | + |
| 81 | + ```typescript |
| 82 | + try { |
| 83 | + const result = await fetchData(); |
| 84 | + } catch (error) { |
| 85 | + logger.error('Data fetch failed', {error}); |
| 86 | + throw new DataFetchError('Unable to fetch data'); |
| 87 | + } |
| 88 | + ``` |
| 89 | + |
| 90 | +### Type Safety |
| 91 | + |
| 92 | +- Prefer interfaces and types. You MUST NOT use `any`. |
| 93 | +- Use type guards and assertions when necessary. |
| 94 | +- Example: |
| 95 | + |
| 96 | + ```typescript |
| 97 | + interface User { |
| 98 | + id: string; |
| 99 | + name: string; |
| 100 | + } |
| 101 | +
|
| 102 | + function isUser(obj: object): obj is User { |
| 103 | + return typeof obj.id === 'string' && typeof obj.name === 'string'; |
| 104 | + } |
| 105 | + ``` |
| 106 | + |
| 107 | +## Security |
| 108 | + |
| 109 | +- Validate and sanitize all external input. |
| 110 | +- Avoid exposing sensitive data in logs or error messages. |
| 111 | +- Use environment variables for secrets and configuration. |
| 112 | +- Keep dependencies up to date and audit regularly. |
| 113 | + |
| 114 | +## Performance |
| 115 | + |
| 116 | +- Minimize synchronous blocking operations. |
| 117 | +- Use async/await for asynchronous code. |
| 118 | +- Avoid unnecessary computations inside render or handler functions. |
| 119 | + |
| 120 | +## Testing |
| 121 | + |
| 122 | +- Write unit tests for all business logic. |
| 123 | +- Use the existing framework for testing and vitest for new packages. |
| 124 | +- Mock external dependencies in tests. |
| 125 | +- Example test file structure: |
| 126 | + |
| 127 | + ``` |
| 128 | + src/ |
| 129 | + handler.ts |
| 130 | + tests/ |
| 131 | + handler.test.ts |
| 132 | + ``` |
| 133 | + |
| 134 | +## JSDoc |
| 135 | + |
| 136 | +- Write concise JSDoc for exported interfaces, types, functions, classes, and exported constants. |
| 137 | +- Prefer short phrase-style summaries; avoid long narrative prose. |
| 138 | +- Avoid stating information that is obvious from function signatures. |
| 139 | +- Consider @param and @returns for every exported function, then include them only when they add meaning not obvious from the signature. |
| 140 | +- Skip @param when it only repeats parameter name/type; keep it when documenting constraints, defaults, units, side effects, or domain context. |
| 141 | +- It is acceptable to use only @returns in a JSDoc block when that tag carries all useful context. |
| 142 | +- Omit a free-text summary line when it only restates the @returns content. |
| 143 | +- Provide @example on constructors of exported types/classes and on non-trivial exported types. |
| 144 | +- Use @default only when the property is optional in the type and is defaulted in implementation. |
| 145 | +- Keep JSDoc defaults aligned with both type signatures and runtime behaviour. |
| 146 | +- For construct props interfaces, include a top-level summary and property docs only when intent is non-obvious. |
| 147 | + |
| 148 | +## Examples and Code Snippets |
| 149 | + |
| 150 | +### Good Example |
| 151 | + |
| 152 | + ```typescript |
| 153 | + interface Prescription { |
| 154 | + id: string; |
| 155 | + medication: string; |
| 156 | + issuedDate: Date; |
| 157 | + } |
| 158 | +
|
| 159 | + function getPrescription(id: string): Prescription | null { |
| 160 | + // Implementation |
| 161 | + } |
| 162 | + ``` |
| 163 | + |
| 164 | +### Bad Example |
| 165 | + |
| 166 | + ```typescript |
| 167 | + function getPrescription(id) { |
| 168 | + // No type safety, unclear return type |
| 169 | + } |
| 170 | + ``` |
| 171 | + |
| 172 | +## Validation and Verification |
| 173 | + |
| 174 | +- Build: `npm run build` |
| 175 | +- Lint: `npm run lint` |
| 176 | +- Format: `npm run format` |
| 177 | +- Test: `npm test` |
| 178 | + |
| 179 | +## Maintenance |
| 180 | + |
| 181 | +- Review and update instructions as dependencies or frameworks change. |
| 182 | +- Update examples to reflect current best practices. |
| 183 | +- Remove deprecated patterns and add new ones as needed. |
| 184 | +- Ensure glob patterns match the intended files. |
| 185 | + |
| 186 | +## Additional Resources |
| 187 | + |
| 188 | +- [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/) |
| 189 | +- [ESLint TypeScript Plugin](https://typescript-eslint.io/) |
| 190 | +- [Prettier Documentation](https://prettier.io/docs/en/options.html) |
0 commit comments