$npx -y skills add sabahattink/antigravity-fullstack-hq --skill typescript-patternsTypeScript type system patterns, generics, utility types, and strict mode best practices. Use when writing or reviewing TypeScript code.
| 1 | # TypeScript Patterns |
| 2 | |
| 3 | ## Core Rules |
| 4 | |
| 5 | - Strict mode always (`"strict": true`) |
| 6 | - No `any` — use `unknown` for dynamic values |
| 7 | - Explicit return types on all functions |
| 8 | - `const` over `let`, never `var` |
| 9 | |
| 10 | ## Type Definitions |
| 11 | |
| 12 | ### Interfaces vs Types |
| 13 | |
| 14 | ```typescript |
| 15 | // ✅ Interface for objects/classes (extensible) |
| 16 | interface User { |
| 17 | id: string |
| 18 | email: string |
| 19 | name: string |
| 20 | } |
| 21 | |
| 22 | // ✅ Type for unions, primitives, computed |
| 23 | type Status = 'active' | 'inactive' | 'pending' |
| 24 | type UserOrAdmin = User | Admin |
| 25 | type ReadonlyUser = Readonly<User> |
| 26 | ``` |
| 27 | |
| 28 | ### Generics |
| 29 | |
| 30 | ```typescript |
| 31 | // ✅ Reusable generic types |
| 32 | type ApiResponse<T> = { |
| 33 | data: T |
| 34 | error: string | null |
| 35 | status: number |
| 36 | } |
| 37 | |
| 38 | type PaginatedResponse<T> = { |
| 39 | items: T[] |
| 40 | total: number |
| 41 | page: number |
| 42 | limit: number |
| 43 | } |
| 44 | |
| 45 | // ✅ Generic functions |
| 46 | const findById = <T extends { id: string }>(items: T[], id: string): T | undefined => |
| 47 | items.find(item => item.id === id) |
| 48 | ``` |
| 49 | |
| 50 | ## Utility Types |
| 51 | |
| 52 | ```typescript |
| 53 | // Pick specific fields |
| 54 | type UserPreview = Pick<User, 'id' | 'name'> |
| 55 | |
| 56 | // Omit sensitive fields |
| 57 | type PublicUser = Omit<User, 'password' | 'salt'> |
| 58 | |
| 59 | // Make all optional (for partial updates) |
| 60 | type UpdateUserDto = Partial<User> |
| 61 | |
| 62 | // Make all required |
| 63 | type RequiredUser = Required<User> |
| 64 | |
| 65 | // Make all readonly |
| 66 | type FrozenUser = Readonly<User> |
| 67 | |
| 68 | // Extract from union |
| 69 | type ActiveStatus = Extract<Status, 'active' | 'pending'> |
| 70 | |
| 71 | // Record type |
| 72 | type UserMap = Record<string, User> |
| 73 | ``` |
| 74 | |
| 75 | ## Discriminated Unions |
| 76 | |
| 77 | ```typescript |
| 78 | // ✅ Type-safe error handling |
| 79 | type Result<T> = |
| 80 | | { success: true; data: T } |
| 81 | | { success: false; error: string } |
| 82 | |
| 83 | const processUser = (id: string): Result<User> => { |
| 84 | try { |
| 85 | return { success: true, data: fetchUser(id) } |
| 86 | } catch (e) { |
| 87 | return { success: false, error: 'User not found' } |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | // Usage — TypeScript knows the type |
| 92 | const result = processUser('123') |
| 93 | if (result.success) { |
| 94 | console.log(result.data.name) // User |
| 95 | } else { |
| 96 | console.log(result.error) // string |
| 97 | } |
| 98 | ``` |
| 99 | |
| 100 | ## Type Guards |
| 101 | |
| 102 | ```typescript |
| 103 | // ✅ Custom type guards |
| 104 | const isUser = (value: unknown): value is User => |
| 105 | typeof value === 'object' && |
| 106 | value !== null && |
| 107 | 'id' in value && |
| 108 | 'email' in value |
| 109 | |
| 110 | // ✅ Assertion functions |
| 111 | const assertDefined = <T>(value: T | null | undefined): T => { |
| 112 | if (value == null) throw new Error('Value is null or undefined') |
| 113 | return value |
| 114 | } |
| 115 | ``` |
| 116 | |
| 117 | ## Async Patterns |
| 118 | |
| 119 | ```typescript |
| 120 | // ✅ Always type async return values |
| 121 | const fetchUser = async (id: string): Promise<User> => { |
| 122 | const res = await fetch(`/api/users/${id}`) |
| 123 | if (!res.ok) throw new Error('Failed to fetch user') |
| 124 | return res.json() as Promise<User> |
| 125 | } |
| 126 | |
| 127 | // ✅ Error handling with unknown |
| 128 | try { |
| 129 | await fetchUser(id) |
| 130 | } catch (error) { |
| 131 | if (error instanceof Error) { |
| 132 | console.error(error.message) |
| 133 | } |
| 134 | } |
| 135 | ``` |
| 136 | |
| 137 | ## Forbidden Patterns |
| 138 | |
| 139 | ```typescript |
| 140 | // ❌ Never |
| 141 | const data: any = fetchData() |
| 142 | function process(x) { return x } // implicit any |
| 143 | const obj = {} as User // unsafe assertion |
| 144 | // @ts-ignore // suppressing errors |
| 145 | ``` |