Created
March 17, 2025 12:33
-
-
Save AleksejDix/ec47da9cedbb010b37634699446632b5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # TypeScript Style Guide (No Interfaces, Classes, or Enums) | |
| ## 1. General Principles | |
| β Prefer **type aliases** over `interface`. | |
| β Use **functional programming** principles. | |
| β Avoid **OOP constructs** like `class`, `interface`, and `enum`. | |
| β Prefer **tuples, records, and discriminated unions**. | |
| β Use `const` and **immutability** wherever possible. | |
| --- | |
| ## 2. File Naming & Conventions | |
| β Use **PascalCase** for components and types. | |
| β Use **camelCase** for functions, variables, and hooks. | |
| β Use **SCREAMING_SNAKE_CASE** for constants. | |
| β Keep **index.ts** for module re-exports. | |
| β Group related files in folders. | |
| ### π **Recommended Folder Structure** | |
| ``` | |
| /src | |
| /components | |
| /Button | |
| index.ts # Exports Button for cleaner imports | |
| Button.ts # Main component logic | |
| Button.styles.ts # Styles (if using styled-components or similar) | |
| Button.test.ts # Unit tests | |
| Button.stories.ts # Storybook stories | |
| /hooks | |
| useAuth.ts # Custom hooks (camelCase) | |
| useTheme.ts | |
| /utils | |
| formatDate.ts # Utility functions (camelCase) | |
| fetchData.ts | |
| /constants | |
| API_ENDPOINTS.ts # Constants (SCREAMING_SNAKE_CASE) | |
| COLORS.ts | |
| /types | |
| userTypes.ts # Shared type definitions (PascalCase for types) | |
| ``` | |
| ### β **Example Import Structure** | |
| ```ts | |
| import { Button } from "@/components/Button"; | |
| import { useAuth } from "@/hooks/useAuth"; | |
| import { formatDate } from "@/utils/formatDate"; | |
| import { API_ENDPOINTS } from "@/constants/API_ENDPOINTS"; | |
| ``` | |
| --- | |
| ## 3. Type Definitions | |
| ### β **Avoid Interfaces** | |
| β **Use `type` instead** | |
| ```ts | |
| // β Bad: Using interfaces | |
| interface User { | |
| id: number; | |
| name: string; | |
| } | |
| // β Good: Using type alias | |
| type User = { | |
| id: number; | |
| name: string; | |
| }; | |
| ``` | |
| --- | |
| ## 4. No Classes | |
| ### β **Avoid Classes** | |
| β **Use functions and object literals** | |
| ```ts | |
| // β Bad: Using a class | |
| class User { | |
| constructor(public id: number, public name: string) {} | |
| } | |
| // β Good: Use a factory function | |
| const createUser = (id: number, name: string) => ({ id, name }); | |
| const user = createUser(1, "Alice"); | |
| ``` | |
| --- | |
| ## 5. No Enums | |
| ### β **Avoid Enums** | |
| β **Use `const` objects or union types** | |
| ```ts | |
| // β Bad: Using enums | |
| enum Status { | |
| Success, | |
| Error, | |
| Loading, | |
| } | |
| // β Good: Use a union type | |
| type Status = "success" | "error" | "loading"; | |
| // β Alternative: Use a const object | |
| const Status = { | |
| Success: "success", | |
| Error: "error", | |
| Loading: "loading", | |
| } as const; | |
| type StatusType = typeof Status[keyof typeof Status]; | |
| ``` | |
| --- | |
| ## 6. Immutability & Functional Programming | |
| β Prefer **readonly** and **immutable structures** | |
| β Use **functional patterns** instead of mutations | |
| ```ts | |
| // β Bad: Mutating objects | |
| const user = { id: 1, name: "Alice" }; | |
| user.name = "Bob"; // Avoid mutating | |
| // β Good: Return a new object | |
| const updatedUser = { ...user, name: "Bob" }; | |
| ``` | |
| --- | |
| ## 7. Use Readonly for Objects & Arrays | |
| ```ts | |
| // β Prevent mutation | |
| type User = Readonly<{ | |
| id: number; | |
| name: string; | |
| }>; | |
| const users: ReadonlyArray<User> = [ | |
| { id: 1, name: "Alice" }, | |
| ]; | |
| // β This will cause a TypeScript error | |
| users[0].name = "Bob"; // Error: Cannot assign to 'name' because it is a read-only property | |
| ``` | |
| --- | |
| ## 8. Use Tuples Instead of Classes | |
| ```ts | |
| // β Bad: Using a class for a point | |
| class Point { | |
| constructor(public x: number, public y: number) {} | |
| } | |
| // β Good: Use a tuple | |
| type Point = readonly [number, number]; | |
| const point: Point = [10, 20]; | |
| ``` | |
| --- | |
| ## 9. Prefer Function Composition | |
| β **Avoid methods inside objects**, prefer **functions that take objects as arguments**. | |
| ```ts | |
| // β Bad: Using a method | |
| const user = { | |
| name: "Alice", | |
| greet() { | |
| return `Hello, ${this.name}`; | |
| }, | |
| }; | |
| // β Good: Function-based approach | |
| const greet = (user: { name: string }) => `Hello, ${user.name}`; | |
| ``` | |
| --- | |
| ## 10. Use Discriminated Unions Instead of Classes | |
| ```ts | |
| // β Bad: Using class inheritance | |
| class Success { | |
| type = "success"; | |
| } | |
| class Error { | |
| type = "error"; | |
| } | |
| // β Good: Use discriminated union | |
| type Response = | |
| | { type: "success"; data: string } | |
| | { type: "error"; message: string }; | |
| const handleResponse = (res: Response) => { | |
| if (res.type === "success") { | |
| console.log(res.data); | |
| } else { | |
| console.log(res.message); | |
| } | |
| }; | |
| ``` | |
| --- | |
| ## 11. Naming Conventions | |
| β Use `camelCase` for variables and functions | |
| β Use `PascalCase` for type aliases | |
| β Use `SCREAMING_SNAKE_CASE` for constants | |
| ```ts | |
| const MAX_USERS = 100; // β Correct | |
| const getUserData = () => {}; // β Correct | |
| type UserProfile = { name: string }; // β Correct | |
| ``` | |
| --- | |
| ## Conclusion | |
| This guide enforces a **functional, immutable, and lightweight** TypeScript codebase by eliminating `interface`, `class`, and `enum`. It encourages **type aliases, discriminated unions, and object literals** for better maintainability and readability. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment