@biggora/claude-plugins 1.2.2 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +5 -1
  2. package/package.json +1 -1
  3. package/registry/registry.json +15 -0
  4. package/specs/coding.md +11 -0
  5. package/src/commands/skills/add.js +115 -31
  6. package/src/commands/skills/list.js +25 -52
  7. package/src/commands/skills/remove.js +45 -27
  8. package/src/commands/skills/resolve.js +104 -0
  9. package/src/commands/skills/update.js +58 -74
  10. package/src/config.js +5 -0
  11. package/src/skills/nest-best-practices/SKILL.md +251 -0
  12. package/src/skills/nest-best-practices/references/best-practices-request-lifecycle.md +158 -0
  13. package/src/skills/nest-best-practices/references/cli-monorepo.md +106 -0
  14. package/src/skills/nest-best-practices/references/cli-overview.md +157 -0
  15. package/src/skills/nest-best-practices/references/core-controllers.md +165 -0
  16. package/src/skills/nest-best-practices/references/core-dependency-injection.md +179 -0
  17. package/src/skills/nest-best-practices/references/core-middleware.md +139 -0
  18. package/src/skills/nest-best-practices/references/core-modules.md +138 -0
  19. package/src/skills/nest-best-practices/references/core-providers.md +188 -0
  20. package/src/skills/nest-best-practices/references/faq-raw-body-hybrid.md +122 -0
  21. package/src/skills/nest-best-practices/references/fundamentals-circular-dependency.md +89 -0
  22. package/src/skills/nest-best-practices/references/fundamentals-custom-decorators.md +107 -0
  23. package/src/skills/nest-best-practices/references/fundamentals-dynamic-modules.md +125 -0
  24. package/src/skills/nest-best-practices/references/fundamentals-exception-filters.md +202 -0
  25. package/src/skills/nest-best-practices/references/fundamentals-execution-context.md +107 -0
  26. package/src/skills/nest-best-practices/references/fundamentals-guards.md +136 -0
  27. package/src/skills/nest-best-practices/references/fundamentals-interceptors.md +187 -0
  28. package/src/skills/nest-best-practices/references/fundamentals-lazy-loading.md +89 -0
  29. package/src/skills/nest-best-practices/references/fundamentals-lifecycle-events.md +87 -0
  30. package/src/skills/nest-best-practices/references/fundamentals-module-reference.md +107 -0
  31. package/src/skills/nest-best-practices/references/fundamentals-pipes.md +197 -0
  32. package/src/skills/nest-best-practices/references/fundamentals-provider-scopes.md +92 -0
  33. package/src/skills/nest-best-practices/references/fundamentals-testing.md +142 -0
  34. package/src/skills/nest-best-practices/references/graphql-overview.md +233 -0
  35. package/src/skills/nest-best-practices/references/graphql-resolvers-mutations.md +199 -0
  36. package/src/skills/nest-best-practices/references/graphql-scalars-unions-enums.md +180 -0
  37. package/src/skills/nest-best-practices/references/graphql-subscriptions.md +228 -0
  38. package/src/skills/nest-best-practices/references/microservices-grpc.md +175 -0
  39. package/src/skills/nest-best-practices/references/microservices-overview.md +221 -0
  40. package/src/skills/nest-best-practices/references/microservices-transports.md +119 -0
  41. package/src/skills/nest-best-practices/references/openapi-swagger.md +207 -0
  42. package/src/skills/nest-best-practices/references/recipes-authentication.md +97 -0
  43. package/src/skills/nest-best-practices/references/recipes-cqrs.md +176 -0
  44. package/src/skills/nest-best-practices/references/recipes-crud-generator.md +87 -0
  45. package/src/skills/nest-best-practices/references/recipes-documentation.md +93 -0
  46. package/src/skills/nest-best-practices/references/recipes-mongoose.md +153 -0
  47. package/src/skills/nest-best-practices/references/recipes-prisma.md +98 -0
  48. package/src/skills/nest-best-practices/references/recipes-terminus.md +148 -0
  49. package/src/skills/nest-best-practices/references/recipes-typeorm.md +122 -0
  50. package/src/skills/nest-best-practices/references/security-authorization.md +196 -0
  51. package/src/skills/nest-best-practices/references/security-cors-helmet-rate-limiting.md +204 -0
  52. package/src/skills/nest-best-practices/references/security-encryption-hashing.md +93 -0
  53. package/src/skills/nest-best-practices/references/techniques-caching.md +142 -0
  54. package/src/skills/nest-best-practices/references/techniques-compression-streaming-sse.md +194 -0
  55. package/src/skills/nest-best-practices/references/techniques-configuration.md +132 -0
  56. package/src/skills/nest-best-practices/references/techniques-database.md +153 -0
  57. package/src/skills/nest-best-practices/references/techniques-events.md +163 -0
  58. package/src/skills/nest-best-practices/references/techniques-fastify.md +137 -0
  59. package/src/skills/nest-best-practices/references/techniques-file-upload.md +140 -0
  60. package/src/skills/nest-best-practices/references/techniques-http-module.md +176 -0
  61. package/src/skills/nest-best-practices/references/techniques-logging.md +146 -0
  62. package/src/skills/nest-best-practices/references/techniques-mvc-serve-static.md +132 -0
  63. package/src/skills/nest-best-practices/references/techniques-queues.md +162 -0
  64. package/src/skills/nest-best-practices/references/techniques-serialization.md +158 -0
  65. package/src/skills/nest-best-practices/references/techniques-sessions-cookies.md +167 -0
  66. package/src/skills/nest-best-practices/references/techniques-task-scheduling.md +166 -0
  67. package/src/skills/nest-best-practices/references/techniques-validation.md +126 -0
  68. package/src/skills/nest-best-practices/references/techniques-versioning.md +153 -0
  69. package/src/skills/nest-best-practices/references/websockets-advanced.md +96 -0
  70. package/src/skills/nest-best-practices/references/websockets-gateways.md +215 -0
  71. package/src/skills/typescript-expert/SKILL.md +145 -0
  72. package/src/skills/typescript-expert/commands/typescript-fix.md +65 -0
  73. package/src/skills/typescript-expert/references/advanced-conditional-types.md +190 -0
  74. package/src/skills/typescript-expert/references/advanced-decorators.md +243 -0
  75. package/src/skills/typescript-expert/references/advanced-mapped-types.md +223 -0
  76. package/src/skills/typescript-expert/references/advanced-template-literals.md +209 -0
  77. package/src/skills/typescript-expert/references/advanced-type-guards.md +308 -0
  78. package/src/skills/typescript-expert/references/best-practices-patterns.md +313 -0
  79. package/src/skills/typescript-expert/references/best-practices-performance.md +185 -0
  80. package/src/skills/typescript-expert/references/best-practices-tsconfig.md +242 -0
  81. package/src/skills/typescript-expert/references/core-generics.md +246 -0
  82. package/src/skills/typescript-expert/references/core-interfaces-types.md +231 -0
  83. package/src/skills/typescript-expert/references/core-type-system.md +261 -0
  84. package/src/skills/typescript-expert/references/core-utility-types.md +235 -0
  85. package/src/skills/typescript-expert/references/features-ts5x.md +370 -0
@@ -0,0 +1,243 @@
1
+ # TC39 Decorators (TypeScript 5.0+)
2
+
3
+ TypeScript 5.0 introduced support for the TC39 Stage 3 decorator proposal. These are **not** the same as legacy `experimentalDecorators` — they have different semantics, no `reflect-metadata`, and work without any compiler flag.
4
+
5
+ ## When to Use Which
6
+
7
+ - **TC39 decorators** (default, no flag): The standard going forward. Use for new code.
8
+ - **`experimentalDecorators`** (tsconfig flag): Legacy. Required by Angular, NestJS, TypeORM, and other frameworks that depend on `reflect-metadata`. Keep using if your framework requires it.
9
+
10
+ Check your framework's documentation — many are migrating to TC39 decorators.
11
+
12
+ ## Class Decorators
13
+
14
+ ```typescript
15
+ // A class decorator receives the class itself and an optional context
16
+ function sealed(target: Function, context: ClassDecoratorContext) {
17
+ Object.seal(target);
18
+ Object.seal(target.prototype);
19
+ }
20
+
21
+ @sealed
22
+ class Greeter {
23
+ greeting: string;
24
+ constructor(message: string) {
25
+ this.greeting = message;
26
+ }
27
+ }
28
+ ```
29
+
30
+ ### Adding Functionality
31
+
32
+ ```typescript
33
+ function withTimestamp<T extends new (...args: any[]) => any>(
34
+ target: T,
35
+ context: ClassDecoratorContext
36
+ ) {
37
+ return class extends target {
38
+ createdAt = new Date();
39
+ };
40
+ }
41
+
42
+ @withTimestamp
43
+ class User {
44
+ name: string;
45
+ constructor(name: string) { this.name = name; }
46
+ }
47
+ ```
48
+
49
+ ## Method Decorators
50
+
51
+ ```typescript
52
+ function log(
53
+ target: Function,
54
+ context: ClassMethodDecoratorContext
55
+ ) {
56
+ const methodName = String(context.name);
57
+ return function (this: any, ...args: any[]) {
58
+ console.log(`Calling ${methodName} with`, args);
59
+ const result = target.call(this, ...args);
60
+ console.log(`${methodName} returned`, result);
61
+ return result;
62
+ };
63
+ }
64
+
65
+ class Calculator {
66
+ @log
67
+ add(a: number, b: number): number {
68
+ return a + b;
69
+ }
70
+ }
71
+ ```
72
+
73
+ ### Bound Method Decorator
74
+
75
+ ```typescript
76
+ function bound(
77
+ target: Function,
78
+ context: ClassMethodDecoratorContext
79
+ ) {
80
+ const methodName = context.name;
81
+ context.addInitializer(function (this: any) {
82
+ this[methodName] = this[methodName].bind(this);
83
+ });
84
+ }
85
+
86
+ class Button {
87
+ label = "Click me";
88
+
89
+ @bound
90
+ handleClick() {
91
+ console.log(this.label); // Always correct `this`
92
+ }
93
+ }
94
+ ```
95
+
96
+ ## Field Decorators
97
+
98
+ ```typescript
99
+ function min(minValue: number) {
100
+ return function (
101
+ target: undefined, // field decorators receive undefined
102
+ context: ClassFieldDecoratorContext
103
+ ) {
104
+ return function (initialValue: number) {
105
+ if (initialValue < minValue) {
106
+ throw new Error(`${String(context.name)} must be >= ${minValue}`);
107
+ }
108
+ return initialValue;
109
+ };
110
+ };
111
+ }
112
+
113
+ class Product {
114
+ @min(0)
115
+ price: number;
116
+
117
+ constructor(price: number) {
118
+ this.price = price;
119
+ }
120
+ }
121
+ ```
122
+
123
+ ## Accessor Decorators
124
+
125
+ The `accessor` keyword (TS 5.0+) creates auto-accessor fields with implicit getter/setter:
126
+
127
+ ```typescript
128
+ class Person {
129
+ accessor name: string;
130
+
131
+ constructor(name: string) {
132
+ this.name = name;
133
+ }
134
+ }
135
+
136
+ // Decorator for accessors
137
+ function validate(
138
+ target: ClassAccessorDecoratorTarget<any, string>,
139
+ context: ClassAccessorDecoratorContext
140
+ ) {
141
+ return {
142
+ set(value: string) {
143
+ if (!value.trim()) throw new Error(`${String(context.name)} cannot be empty`);
144
+ target.set.call(this, value);
145
+ },
146
+ get() {
147
+ return target.get.call(this);
148
+ },
149
+ };
150
+ }
151
+
152
+ class User {
153
+ @validate
154
+ accessor name: string = "";
155
+ }
156
+ ```
157
+
158
+ ## Decorator Factories
159
+
160
+ Most real-world decorators are factories — functions that return decorators:
161
+
162
+ ```typescript
163
+ function retry(attempts: number) {
164
+ return function (
165
+ target: Function,
166
+ context: ClassMethodDecoratorContext
167
+ ) {
168
+ return async function (this: any, ...args: any[]) {
169
+ for (let i = 0; i < attempts; i++) {
170
+ try {
171
+ return await target.call(this, ...args);
172
+ } catch (err) {
173
+ if (i === attempts - 1) throw err;
174
+ }
175
+ }
176
+ };
177
+ };
178
+ }
179
+
180
+ class ApiClient {
181
+ @retry(3)
182
+ async fetchData(url: string): Promise<Response> {
183
+ return fetch(url);
184
+ }
185
+ }
186
+ ```
187
+
188
+ ## Decorator Context Types
189
+
190
+ Each decorator kind has a specific context type:
191
+
192
+ | Decorator Target | Context Type |
193
+ |------------------|-------------|
194
+ | Class | `ClassDecoratorContext` |
195
+ | Method | `ClassMethodDecoratorContext` |
196
+ | Getter | `ClassGetterDecoratorContext` |
197
+ | Setter | `ClassSetterDecoratorContext` |
198
+ | Field | `ClassFieldDecoratorContext` |
199
+ | Auto-accessor | `ClassAccessorDecoratorContext` |
200
+
201
+ All context types include:
202
+ - `name`: The name of the decorated element
203
+ - `kind`: "class", "method", "getter", "setter", "field", or "accessor"
204
+ - `static`: Whether the element is static
205
+ - `private`: Whether the element is private
206
+ - `addInitializer()`: Register a callback to run during construction
207
+ - `metadata`: Shared metadata object (replaces `reflect-metadata`)
208
+
209
+ ## Metadata (TC39 Decorator Metadata)
210
+
211
+ TC39 decorators have a built-in metadata mechanism:
212
+
213
+ ```typescript
214
+ function meta(key: string, value: any) {
215
+ return function (_target: any, context: ClassMethodDecoratorContext) {
216
+ context.metadata[key] = value;
217
+ };
218
+ }
219
+
220
+ class Routes {
221
+ @meta("path", "/users")
222
+ @meta("method", "GET")
223
+ getUsers() { ... }
224
+ }
225
+
226
+ // Access metadata
227
+ const metadata = Routes[Symbol.metadata];
228
+ // { path: "/users", method: "GET" }
229
+ ```
230
+
231
+ ## Migration from `experimentalDecorators`
232
+
233
+ Key differences:
234
+
235
+ | `experimentalDecorators` | TC39 Decorators |
236
+ |--------------------------|-----------------|
237
+ | Receives `(target, key, descriptor)` | Receives `(value, context)` |
238
+ | Uses `reflect-metadata` for metadata | Uses `context.metadata` |
239
+ | Parameter decorators supported | No parameter decorators |
240
+ | `emitDecoratorMetadata` flag | No equivalent (use `context.metadata`) |
241
+ | Runs at class definition time | Runs at class definition time |
242
+
243
+ Parameter decorators are **not** part of TC39 decorators. Frameworks that need them (like NestJS for DI) still require `experimentalDecorators`.
@@ -0,0 +1,223 @@
1
+ # Mapped Types
2
+
3
+ Mapped types transform every property in an existing type, producing a new type. They iterate over keys and apply transformations.
4
+
5
+ ## Basic Syntax
6
+
7
+ ```typescript
8
+ type Mapped<T> = {
9
+ [K in keyof T]: T[K];
10
+ };
11
+ ```
12
+
13
+ This is the identity mapped type — it produces the same type. The power comes from modifying the value type or the key.
14
+
15
+ ## Adding/Removing Modifiers
16
+
17
+ ```typescript
18
+ // Add readonly to all properties
19
+ type Readonly<T> = {
20
+ readonly [K in keyof T]: T[K];
21
+ };
22
+
23
+ // Remove readonly with -readonly
24
+ type Mutable<T> = {
25
+ -readonly [K in keyof T]: T[K];
26
+ };
27
+
28
+ // Make all properties optional
29
+ type Partial<T> = {
30
+ [K in keyof T]?: T[K];
31
+ };
32
+
33
+ // Remove optionality with -?
34
+ type Required<T> = {
35
+ [K in keyof T]-?: T[K];
36
+ };
37
+
38
+ // Combine: mutable and required
39
+ type Concrete<T> = {
40
+ -readonly [K in keyof T]-?: T[K];
41
+ };
42
+ ```
43
+
44
+ ## Key Remapping with `as` (TS 4.1+)
45
+
46
+ Remap keys during iteration using `as`:
47
+
48
+ ```typescript
49
+ // Rename keys with a template literal
50
+ type Getters<T> = {
51
+ [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
52
+ };
53
+
54
+ interface Person { name: string; age: number }
55
+ type PersonGetters = Getters<Person>;
56
+ // { getName: () => string; getAge: () => number }
57
+
58
+ // Filter keys by remapping to never
59
+ type RemoveFunctions<T> = {
60
+ [K in keyof T as T[K] extends Function ? never : K]: T[K];
61
+ };
62
+
63
+ interface Mixed {
64
+ name: string;
65
+ age: number;
66
+ greet(): void;
67
+ }
68
+ type DataOnly = RemoveFunctions<Mixed>;
69
+ // { name: string; age: number }
70
+ ```
71
+
72
+ ## Iterating Over Unions
73
+
74
+ Mapped types can iterate over any union of string literals, not just `keyof`:
75
+
76
+ ```typescript
77
+ type EventMap = {
78
+ [K in "click" | "hover" | "focus"]: (e: Event) => void;
79
+ };
80
+ // { click: (e: Event) => void; hover: (e: Event) => void; focus: (e: Event) => void }
81
+
82
+ // Using a union of string literals from an enum-like const
83
+ const EVENTS = ["click", "hover", "focus"] as const;
84
+ type EventHandlers = {
85
+ [K in (typeof EVENTS)[number] as `on${Capitalize<K>}`]: (e: Event) => void;
86
+ };
87
+ // { onClick: (e: Event) => void; onHover: (e: Event) => void; onFocus: (e: Event) => void }
88
+ ```
89
+
90
+ ## Practical Patterns
91
+
92
+ ### Making Specific Properties Optional
93
+
94
+ ```typescript
95
+ type OptionalBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
96
+
97
+ interface User {
98
+ id: string;
99
+ name: string;
100
+ email: string;
101
+ }
102
+ type CreateUser = OptionalBy<User, "id">;
103
+ // { name: string; email: string; id?: string }
104
+ ```
105
+
106
+ ### Deep Partial
107
+
108
+ ```typescript
109
+ type DeepPartial<T> = {
110
+ [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
111
+ };
112
+
113
+ interface Config {
114
+ server: { host: string; port: number };
115
+ db: { url: string; pool: { min: number; max: number } };
116
+ }
117
+
118
+ type PartialConfig = DeepPartial<Config>;
119
+ // All nested properties are optional
120
+ ```
121
+
122
+ ### Deep Readonly
123
+
124
+ ```typescript
125
+ type DeepReadonly<T> = {
126
+ readonly [K in keyof T]: T[K] extends object
127
+ ? T[K] extends Function
128
+ ? T[K]
129
+ : DeepReadonly<T[K]>
130
+ : T[K];
131
+ };
132
+ ```
133
+
134
+ ### Nullable Properties
135
+
136
+ ```typescript
137
+ type Nullable<T> = {
138
+ [K in keyof T]: T[K] | null;
139
+ };
140
+ ```
141
+
142
+ ### Event Emitter Types
143
+
144
+ ```typescript
145
+ type EventEmitter<Events extends Record<string, any[]>> = {
146
+ on<K extends keyof Events>(event: K, handler: (...args: Events[K]) => void): void;
147
+ emit<K extends keyof Events>(event: K, ...args: Events[K]): void;
148
+ };
149
+
150
+ interface MyEvents {
151
+ login: [user: User];
152
+ error: [code: number, message: string];
153
+ logout: [];
154
+ }
155
+
156
+ declare const emitter: EventEmitter<MyEvents>;
157
+ emitter.on("login", (user) => { ... }); // user: User
158
+ emitter.on("error", (code, msg) => { ... }); // code: number, msg: string
159
+ emitter.emit("logout"); // no args
160
+ ```
161
+
162
+ ### API Route Types
163
+
164
+ ```typescript
165
+ type ApiRoutes = {
166
+ "/users": { GET: User[]; POST: User };
167
+ "/users/:id": { GET: User; PUT: User; DELETE: void };
168
+ };
169
+
170
+ type RouteHandler<
171
+ Routes extends Record<string, Record<string, any>>,
172
+ Path extends keyof Routes,
173
+ Method extends keyof Routes[Path]
174
+ > = () => Promise<Routes[Path][Method]>;
175
+ ```
176
+
177
+ ### Record-Like with Constraints
178
+
179
+ ```typescript
180
+ // Like Record, but values depend on the key
181
+ type TypedRecord<K extends string, ValueFn extends Record<K, any>> = {
182
+ [P in K]: ValueFn[P];
183
+ };
184
+
185
+ // Each validator returns the type it validates
186
+ type Validators = TypedRecord<
187
+ "name" | "age",
188
+ { name: string; age: number }
189
+ >;
190
+ // { name: string; age: number }
191
+ ```
192
+
193
+ ## Combining with Conditional Types
194
+
195
+ ```typescript
196
+ // Make all function properties async
197
+ type Asyncify<T> = {
198
+ [K in keyof T]: T[K] extends (...args: infer A) => infer R
199
+ ? (...args: A) => Promise<R>
200
+ : T[K];
201
+ };
202
+
203
+ interface Sync {
204
+ getData(): string;
205
+ count: number;
206
+ }
207
+ type Async = Asyncify<Sync>;
208
+ // { getData: () => Promise<string>; count: number }
209
+ ```
210
+
211
+ ## Homomorphic vs Non-Homomorphic
212
+
213
+ A mapped type is **homomorphic** when it maps over `keyof T` (preserving modifiers from the original):
214
+
215
+ ```typescript
216
+ // Homomorphic — preserves optional/readonly from T
217
+ type Clone<T> = { [K in keyof T]: T[K] };
218
+
219
+ // Non-homomorphic — uses an independent key set
220
+ type FromKeys<K extends string> = { [P in K]: unknown };
221
+ ```
222
+
223
+ Homomorphic mapped types automatically preserve `readonly` and `?` modifiers unless explicitly removed with `-readonly` or `-?`.
@@ -0,0 +1,209 @@
1
+ # Template Literal Types
2
+
3
+ Template literal types build string types from other types using template literal syntax. They're TypeScript's most powerful tool for type-safe string manipulation.
4
+
5
+ ## Basic Syntax
6
+
7
+ ```typescript
8
+ type Greeting = `Hello, ${string}`;
9
+ // Matches "Hello, Alice", "Hello, Bob", "Hello, " — any string after "Hello, "
10
+
11
+ type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
12
+ type Endpoint = `/api/${string}`;
13
+ type ApiCall = `${HttpMethod} ${Endpoint}`;
14
+ // "GET /api/..." | "POST /api/..." | "PUT /api/..." | "DELETE /api/..."
15
+ ```
16
+
17
+ ## Union Expansion
18
+
19
+ When unions appear in template literal positions, the result is the cross product:
20
+
21
+ ```typescript
22
+ type Suit = "hearts" | "diamonds" | "clubs" | "spades";
23
+ type Rank = "A" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "J" | "Q" | "K";
24
+ type Card = `${Rank} of ${Suit}`;
25
+ // "A of hearts" | "A of diamonds" | ... | "K of spades" (52 members)
26
+
27
+ type Size = "sm" | "md" | "lg";
28
+ type Color = "red" | "blue" | "green";
29
+ type Variant = `${Size}-${Color}`;
30
+ // "sm-red" | "sm-blue" | "sm-green" | "md-red" | ... (9 members)
31
+ ```
32
+
33
+ ## Intrinsic String Manipulation Types
34
+
35
+ TypeScript provides four built-in types that transform string literals:
36
+
37
+ ```typescript
38
+ type A = Uppercase<"hello">; // "HELLO"
39
+ type B = Lowercase<"HELLO">; // "hello"
40
+ type C = Capitalize<"hello">; // "Hello"
41
+ type D = Uncapitalize<"Hello">; // "hello"
42
+
43
+ // Combined with template literals
44
+ type EventHandler<T extends string> = `on${Capitalize<T>}`;
45
+ type Click = EventHandler<"click">; // "onClick"
46
+ type KeyDown = EventHandler<"keyDown">; // "onKeyDown"
47
+ ```
48
+
49
+ ## Pattern Matching with `infer`
50
+
51
+ Template literals can extract parts of string types:
52
+
53
+ ```typescript
54
+ // Extract the event name from "on{Event}"
55
+ type ExtractEvent<T> = T extends `on${infer E}` ? Uncapitalize<E> : never;
56
+ type A = ExtractEvent<"onClick">; // "click"
57
+ type B = ExtractEvent<"onKeyDown">; // "keyDown"
58
+ type C = ExtractEvent<"submit">; // never
59
+
60
+ // Parse dot-separated paths
61
+ type FirstSegment<T extends string> = T extends `${infer Head}.${string}` ? Head : T;
62
+ type D = FirstSegment<"user.address.city">; // "user"
63
+ type E = FirstSegment<"name">; // "name"
64
+
65
+ // Split a string type
66
+ type Split<S extends string, D extends string> =
67
+ S extends `${infer Head}${D}${infer Tail}`
68
+ ? [Head, ...Split<Tail, D>]
69
+ : [S];
70
+
71
+ type F = Split<"a.b.c", ".">; // ["a", "b", "c"]
72
+ ```
73
+
74
+ ## Practical Patterns
75
+
76
+ ### Type-Safe Event System
77
+
78
+ ```typescript
79
+ type EventMap = {
80
+ click: { x: number; y: number };
81
+ keydown: { key: string };
82
+ resize: { width: number; height: number };
83
+ };
84
+
85
+ type EventHandlerName<T extends string> = `on${Capitalize<T>}`;
86
+
87
+ type EventHandlers<E extends Record<string, any>> = {
88
+ [K in keyof E as EventHandlerName<string & K>]?: (event: E[K]) => void;
89
+ };
90
+
91
+ type MyHandlers = EventHandlers<EventMap>;
92
+ // { onClick?: (event: { x: number; y: number }) => void;
93
+ // onKeydown?: (event: { key: string }) => void;
94
+ // onResize?: (event: { width: number; height: number }) => void; }
95
+ ```
96
+
97
+ ### Type-Safe CSS Properties
98
+
99
+ ```typescript
100
+ type CSSUnit = "px" | "em" | "rem" | "%" | "vh" | "vw";
101
+ type CSSValue = `${number}${CSSUnit}` | "auto" | "inherit";
102
+
103
+ function setWidth(el: HTMLElement, width: CSSValue) {
104
+ el.style.width = width;
105
+ }
106
+
107
+ setWidth(el, "100px"); // OK
108
+ setWidth(el, "2.5rem"); // OK
109
+ setWidth(el, "auto"); // OK
110
+ setWidth(el, "100"); // Error — missing unit
111
+ ```
112
+
113
+ ### Route Parameter Extraction
114
+
115
+ ```typescript
116
+ type ExtractParams<T extends string> =
117
+ T extends `${string}:${infer Param}/${infer Rest}`
118
+ ? Param | ExtractParams<`/${Rest}`>
119
+ : T extends `${string}:${infer Param}`
120
+ ? Param
121
+ : never;
122
+
123
+ type Params = ExtractParams<"/users/:userId/posts/:postId">;
124
+ // "userId" | "postId"
125
+
126
+ type RouteParams<T extends string> = {
127
+ [K in ExtractParams<T>]: string;
128
+ };
129
+
130
+ type UserPostParams = RouteParams<"/users/:userId/posts/:postId">;
131
+ // { userId: string; postId: string }
132
+ ```
133
+
134
+ ### SQL Column Type Mapping
135
+
136
+ ```typescript
137
+ type SQLType = "TEXT" | "INTEGER" | "BOOLEAN" | "TIMESTAMP";
138
+
139
+ type TSTypeMap = {
140
+ TEXT: string;
141
+ INTEGER: number;
142
+ BOOLEAN: boolean;
143
+ TIMESTAMP: Date;
144
+ };
145
+
146
+ type ColumnDef<Name extends string, Type extends SQLType> = `${Name} ${Type}`;
147
+
148
+ type ParseColumn<T> = T extends `${infer Name} ${infer Type extends SQLType}`
149
+ ? { name: Name; type: TSTypeMap[Type] }
150
+ : never;
151
+
152
+ type Col = ParseColumn<"username TEXT">;
153
+ // { name: "username"; type: string }
154
+ ```
155
+
156
+ ### Deep Property Paths
157
+
158
+ ```typescript
159
+ type PropPath<T, Prefix extends string = ""> = {
160
+ [K in keyof T & string]: T[K] extends object
161
+ ? PropPath<T[K], `${Prefix}${K}.`>
162
+ : `${Prefix}${K}`;
163
+ }[keyof T & string];
164
+
165
+ interface User {
166
+ name: string;
167
+ address: {
168
+ city: string;
169
+ zip: string;
170
+ };
171
+ }
172
+
173
+ type UserPaths = PropPath<User>;
174
+ // "name" | "address.city" | "address.zip"
175
+ ```
176
+
177
+ ## Template Literals as Discriminants (TS 4.5+)
178
+
179
+ Template literal types can serve as discriminants in unions:
180
+
181
+ ```typescript
182
+ interface SuccessResponse {
183
+ type: `${string}Success`;
184
+ data: unknown;
185
+ }
186
+
187
+ interface ErrorResponse {
188
+ type: `${string}Error`;
189
+ message: string;
190
+ }
191
+
192
+ function handle(r: SuccessResponse | ErrorResponse) {
193
+ if (r.type === "ApiSuccess") {
194
+ r.data; // SuccessResponse narrowed
195
+ }
196
+ }
197
+ ```
198
+
199
+ ## Performance Considerations
200
+
201
+ Template literal unions grow multiplicatively. A cross product of two unions with 10 members each creates 100 members. TypeScript limits union sizes (around 100,000 members), so avoid unbounded cross products:
202
+
203
+ ```typescript
204
+ // This is fine — 3 x 3 = 9 members
205
+ type Small = `${1 | 2 | 3}-${"a" | "b" | "c"}`;
206
+
207
+ // This would be problematic — string has infinite members
208
+ // type Bad = `${string}-${string}`; // Works but can't enumerate
209
+ ```