@elliots/typical 0.1.10 → 0.2.0

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 (56) hide show
  1. package/README.md +234 -200
  2. package/dist/src/cli.js +12 -85
  3. package/dist/src/cli.js.map +1 -1
  4. package/dist/src/cli.typical.ts +136 -0
  5. package/dist/src/config.d.ts +12 -0
  6. package/dist/src/config.js +40 -38
  7. package/dist/src/config.js.map +1 -1
  8. package/dist/src/config.typical.ts +287 -0
  9. package/dist/src/esm-loader-register.js.map +1 -1
  10. package/dist/src/esm-loader.d.ts +1 -1
  11. package/dist/src/esm-loader.js +30 -17
  12. package/dist/src/esm-loader.js.map +1 -1
  13. package/dist/src/file-filter.d.ts +1 -1
  14. package/dist/src/file-filter.js.map +1 -1
  15. package/dist/src/index.d.ts +5 -4
  16. package/dist/src/index.js +1 -1
  17. package/dist/src/index.js.map +1 -1
  18. package/dist/src/program-manager.d.ts +27 -0
  19. package/dist/src/program-manager.js +121 -0
  20. package/dist/src/program-manager.js.map +1 -0
  21. package/dist/src/regex-hoister.d.ts +1 -1
  22. package/dist/src/regex-hoister.js +13 -19
  23. package/dist/src/regex-hoister.js.map +1 -1
  24. package/dist/src/setup.d.ts +1 -1
  25. package/dist/src/setup.js +3 -3
  26. package/dist/src/setup.js.map +1 -1
  27. package/dist/src/source-map.d.ts +1 -1
  28. package/dist/src/source-map.js +1 -1
  29. package/dist/src/source-map.js.map +1 -1
  30. package/dist/src/source-map.typical.ts +216 -0
  31. package/dist/src/timing.d.ts +19 -0
  32. package/dist/src/timing.js +65 -0
  33. package/dist/src/timing.js.map +1 -0
  34. package/dist/src/transformer.d.ts +28 -193
  35. package/dist/src/transformer.js +41 -1917
  36. package/dist/src/transformer.js.map +1 -1
  37. package/dist/src/transformer.typical.ts +2552 -0
  38. package/dist/src/tsc-plugin.d.ts +8 -1
  39. package/dist/src/tsc-plugin.js +11 -7
  40. package/dist/src/tsc-plugin.js.map +1 -1
  41. package/package.json +51 -47
  42. package/src/cli.ts +41 -128
  43. package/src/config.ts +106 -91
  44. package/src/esm-loader-register.ts +2 -2
  45. package/src/esm-loader.ts +44 -29
  46. package/src/index.ts +5 -10
  47. package/src/patch-fs.cjs +14 -14
  48. package/src/timing.ts +74 -0
  49. package/src/transformer.ts +47 -2592
  50. package/bin/ttsc +0 -12
  51. package/src/file-filter.ts +0 -49
  52. package/src/patch-tsconfig.cjs +0 -52
  53. package/src/regex-hoister.ts +0 -203
  54. package/src/setup.ts +0 -39
  55. package/src/source-map.ts +0 -202
  56. package/src/tsc-plugin.ts +0 -12
package/README.md CHANGED
@@ -1,113 +1,129 @@
1
1
  # Typical
2
2
 
3
- Typical adds runtime validation to typescript, making TypeScript type-safe at runtime *with no changes to your code*.
3
+ Typical makes TypeScript type-safe at runtime _with no changes to your code_.
4
4
 
5
- It can be used as a TSC plugin, ESM loader for Node.js, or with bundlers like Vite, Webpack, and Rollup via unplugin.
5
+ It transforms your code to inject runtime validation based on your existing type annotations. With source maps, so errors point to the right lines in your original code.
6
6
 
7
7
  ## Why?
8
8
 
9
- For some use cases it can mean you don't need to use zod, yup, ajv, or other runtime validation libraries, as your types are already validated automatically.
9
+ - Less need for zod, yup, ajv, or other runtime validation libraries - your types are already validated automatically. If you can express it in TypeScript, Typical can validate it at runtime.
10
+ - Protects against data leaks via `JSON.stringify` by ensuring only properties defined in your types are included
11
+ - Catches type mismatches at runtime that TypeScript can't catch at compile time (API responses, JSON parsing, un-typed/badly-typed libraries, vibe-coding coworkers etc.)
10
12
 
11
- It protects you from leaking data via JSON.stringify by making sure only the properties defined in your types are included in the output.
13
+ ## Features
12
14
 
13
- Why not.
15
+ - Validation of function parameters and return types
16
+ - Safe `JSON.parse` with type validation
17
+ - Safe `JSON.stringify` that only includes defined properties
18
+ - Validation of type casts (`as Type`)
19
+ - Configurable include/exclude patterns
14
20
 
15
- ## Features
21
+ ## Example
16
22
 
17
- - Automatic validation of function parameters
18
- - ✅ Automatic validation of return types
19
- - ✅ Replace `JSON.stringify` with a custom stringifier (very fast!)
20
- - ✅ Replace `JSON.parse` with a custom parser and validator (very fast!)
21
- - ✅ Configurable include/exclude patterns
22
- - ✅ Optionally reuse validation logic for identical types to optimize performance (enabled by default)
23
- - ✅ TSC plugin
24
- - ✅ ESM loader for runtime transformation with `node --import @elliots/typical/esm` (or `node --loader @elliots/typical/esm-loader` for older Node versions)
25
- - ✅ tsx wrapper (ttsx) for easy use like `npx ttsx script.ts`
26
- - ✅ Unplugin for Vite, Webpack, Rollup, esbuild, and more
23
+ This code runs without errors in normal TypeScript, but Typical catches the invalid data:
27
24
 
28
- ## Installation
25
+ ```ts
26
+ interface User {
27
+ name: string;
28
+ email: `${string}@${string}`;
29
+ }
29
30
 
30
- ```bash
31
- npm add typical
31
+ // This will throw - email doesn't match the template literal type
32
+ const user = JSON.parse('{"name":"Alice","email":"not-an-email"}') as User;
32
33
  ```
33
34
 
34
- ## Configuration
35
+ ---
36
+
37
+ ## Usage Options
38
+
39
+ Choose the integration that fits your workflow:
40
+
41
+ | Method | Best For | Package |
42
+ | --------------------------------------------------------- | ------------------------------- | ----------------------------- |
43
+ | [ESM Loader](#nodejs-esm-loader) | Node.js scripts, development | `@elliots/typical` |
44
+ | [ttsx](#ttsx-tsx-wrapper) | Quick scripts with tsx | `@elliots/typical` + `tsx` |
45
+ | [Bun Plugin](#bun) | Bun projects | `@elliots/bun-plugin-typical` |
46
+ | [Vite/Webpack/etc](#bundlers-vite-webpack-rollup-esbuild) | Frontend apps, bundled projects | `@elliots/unplugin-typical` |
47
+ | [tsc Plugin](#typescript-compiler-tsc) | Pure TypeScript compilation | `@elliots/typical-tsc-plugin` |
48
+
49
+ ---
50
+
51
+ ## Node.js (ESM Loader)
35
52
 
36
- Optional: Create a `typical.json` file in your project root.
53
+ The simplest way to run TypeScript with Typical validation.
37
54
 
38
- If not provided, these default settings will be used (optimized for development):
55
+ ```bash
56
+ npm add @elliots/typical
57
+ ```
58
+
59
+ ```bash
60
+ node --import @elliots/typical/esm src/index.ts
61
+ ```
62
+
63
+ Add to `package.json` scripts:
39
64
 
40
65
  ```json
41
66
  {
42
- "include": ["**/*.ts", "**/*.tsx"],
43
- "exclude": ["node_modules/**", "**/*.d.ts", "dist/**", "build/**"],
44
- "reusableValidators": false,
45
- "validateFunctions": true,
46
- "validateCasts": false,
47
- "hoistRegex": true,
48
- "ignoreDOMTypes": true,
49
- "ignoreTypes": [],
50
- "sourceMap": {
51
- "enabled": true,
52
- "includeContent": true,
53
- "inline": false
67
+ "scripts": {
68
+ "start": "node --import @elliots/typical/esm src/index.ts"
54
69
  }
55
70
  }
56
71
  ```
57
72
 
58
- ### Configuration Options
73
+ ---
59
74
 
60
- | Option | Default | Description |
61
- |--------|---------|-------------|
62
- | `include` | `["**/*.ts", "**/*.tsx"]` | Glob patterns for files to transform |
63
- | `exclude` | `["node_modules/**", "**/*.d.ts", "dist/**", "build/**"]` | Glob patterns for files to skip |
64
- | `reusableValidators` | `false` | Create shared validators for identical types (smaller output). Incompatible with source maps. |
65
- | `validateFunctions` | `true` | Validate function parameters and return types at runtime |
66
- | `validateCasts` | `false` | Validate type assertions (`as Type`) at runtime |
67
- | `hoistRegex` | `true` | Hoist regex patterns to top-level constants (improves performance) |
68
- | `ignoreDOMTypes` | `true` | Skip validation for DOM types (Document, Element, etc.) |
69
- | `ignoreTypes` | `[]` | Type patterns to skip validation for (supports wildcards, e.g., `["React.*"]`) |
70
- | `sourceMap.enabled` | `true` | Generate source maps for transformed code |
71
- | `sourceMap.includeContent` | `true` | Include original source content in source maps |
72
- | `sourceMap.inline` | `false` | Use inline source maps (data URL) instead of external files |
73
- | `debug.writeIntermediateFiles` | `false` | Write `.typical.ts` files showing code before typia transform |
75
+ ## ttsx (tsx wrapper)
74
76
 
75
- ### Production Configuration
77
+ A convenience wrapper that combines [tsx](https://github.com/privatenumber/tsx) with Typical.
76
78
 
77
- For production builds, disable source maps and enable reusable validators for smaller output:
79
+ ```bash
80
+ npm add @elliots/typical tsx
81
+ ```
78
82
 
79
- ```json
80
- {
81
- "reusableValidators": true,
82
- "sourceMap": {
83
- "enabled": false
84
- }
85
- }
83
+ ```bash
84
+ npx ttsx script.ts
86
85
  ```
87
86
 
88
- Note: `reusableValidators` and `sourceMap.enabled` are mutually exclusive. Source maps require inline validators so each validation call can map back to its original type annotation. If both are enabled, `reusableValidators` will be automatically disabled with a warning.
87
+ Or install globally:
88
+
89
+ ```bash
90
+ npm add -g @elliots/typical tsx
91
+ ttsx script.ts
92
+ ```
89
93
 
90
- ## Usage
94
+ > **Note:** `tsx` must be installed separately. The `ttsx` command is a thin wrapper that runs `tsx` with the Typical ESM loader.
91
95
 
92
- See ./samples/esm and ./samples/tsc and ./samples/ttsx
96
+ ---
93
97
 
94
- Quickest way to try it out is to use ttsx:
98
+ ## Bun
95
99
 
96
100
  ```bash
97
- npm add @elliots/typical
98
- npx ttsx your-script.ts
101
+ bun add @elliots/bun-plugin-typical
102
+ ```
103
+
104
+ Create `bunfig.toml`:
105
+
106
+ ```toml
107
+ preload = ["./preload.ts"]
99
108
  ```
100
109
 
101
- or globally:
110
+ Create `preload.ts`:
111
+
112
+ ```ts
113
+ import { typicalPlugin } from "@elliots/bun-plugin-typical";
114
+
115
+ Bun.plugin(typicalPlugin());
116
+ ```
117
+
118
+ Then run:
102
119
 
103
120
  ```bash
104
- npm add -g @elliots/typical
105
- ttsx your-script.ts
121
+ bun run src/index.ts
106
122
  ```
107
123
 
108
- ## Vite / Webpack / Rollup (unplugin)
124
+ ---
109
125
 
110
- Install the unplugin:
126
+ ## Bundlers (Vite, Webpack, Rollup, esbuild)
111
127
 
112
128
  ```bash
113
129
  npm add @elliots/unplugin-typical
@@ -115,224 +131,242 @@ npm add @elliots/unplugin-typical
115
131
 
116
132
  ### Vite
117
133
 
118
- ```typescript
134
+ ```ts
119
135
  // vite.config.ts
120
- import Typical from '@elliots/unplugin-typical/vite'
136
+ import Typical from "@elliots/unplugin-typical/vite";
121
137
 
122
138
  export default defineConfig({
123
- plugins: [
124
- Typical(),
125
- ],
126
- })
139
+ plugins: [Typical()],
140
+ });
127
141
  ```
128
142
 
129
143
  ### Webpack
130
144
 
131
- ```typescript
145
+ ```js
132
146
  // webpack.config.js
133
- const Typical = require('@elliots/unplugin-typical/webpack').default
147
+ const Typical = require("@elliots/unplugin-typical/webpack").default;
134
148
 
135
149
  module.exports = {
136
- plugins: [
137
- Typical(),
138
- ],
139
- }
150
+ plugins: [Typical()],
151
+ };
140
152
  ```
141
153
 
142
154
  ### Rollup
143
155
 
144
- ```typescript
156
+ ```js
145
157
  // rollup.config.js
146
- import Typical from '@elliots/unplugin-typical/rollup'
158
+ import Typical from "@elliots/unplugin-typical/rollup";
147
159
 
148
160
  export default {
149
- plugins: [
150
- Typical(),
151
- ],
152
- }
161
+ plugins: [Typical()],
162
+ };
153
163
  ```
154
164
 
155
165
  ### esbuild
156
166
 
157
- ```typescript
158
- import { build } from 'esbuild'
159
- import Typical from '@elliots/unplugin-typical/esbuild'
167
+ ```ts
168
+ import { build } from "esbuild";
169
+ import Typical from "@elliots/unplugin-typical/esbuild";
160
170
 
161
171
  build({
162
172
  plugins: [Typical()],
163
- })
173
+ });
164
174
  ```
165
175
 
166
- ### Plugin Configuration
176
+ ### Rolldown
167
177
 
168
- Pass options directly to the plugin:
178
+ ```ts
179
+ // rolldown.config.ts
180
+ import Typical from "@elliots/unplugin-typical/rolldown";
169
181
 
170
- ```typescript
171
- Typical({
172
- validateFunctions: true,
173
- validateCasts: false,
174
- // ... other options
175
- })
182
+ export default {
183
+ plugins: [Typical()],
184
+ };
176
185
  ```
177
186
 
178
- Or use a `typical.json` file in your project root (shared with other entry points like TSC plugin and ESM loader).
187
+ ### Farm
179
188
 
180
- ## Example
189
+ ```ts
190
+ // farm.config.ts
191
+ import Typical from "@elliots/unplugin-typical/farm";
181
192
 
182
- This code will run without errors when compiled normally, but will throw an error when using Typical.
193
+ export default {
194
+ plugins: [Typical()],
195
+ };
196
+ ```
183
197
 
198
+ ### Rspack
184
199
 
185
200
  ```ts
186
- interface User {
187
- name: string;
188
- email: `${string}@${string}`;
189
- }
190
- const u = JSON.parse('{"name":"Alice","email":"oops-not-an-email"}') as User;
201
+ // rspack.config.ts
202
+ import Typical from "@elliots/unplugin-typical/rspack";
203
+
204
+ export default {
205
+ plugins: [Typical()],
206
+ };
191
207
  ```
192
208
 
193
- ## How it works
209
+ ---
194
210
 
195
- Typical uses the TypeScript Compiler API to parse and transform your TypeScript code. It analyzes function signatures, return types, and JSON operations to inject appropriate typia validation calls.
211
+ ## TypeScript Compiler (tsc)
196
212
 
197
- But basically you shouldn't need to care about how it works internally, it makes typescript strongly typed*. You can still use `any` and `unknown` if you want to opt out of type safety.
213
+ For projects that compile with `tsc` directly using [ts-patch](https://github.com/nonara/ts-patch).
198
214
 
199
- * sort of. probably. something like it anyway.
215
+ ```bash
216
+ npm add @elliots/typical-tsc-plugin ts-patch
217
+ ```
200
218
 
201
- ## Flow Analysis
219
+ ### Option 1: ttsc (auto-injects plugin)
202
220
 
203
- Typical includes smart flow analysis to avoid redundant validations. When you return a value that was already validated (either as a parameter or via a type-annotated const), the return statement won't be wrapped in another validation call.
221
+ The `ttsc` command automatically injects the plugin - no config needed:
204
222
 
205
- ### When return validation is skipped:
223
+ ```bash
224
+ npx ttsc
225
+ ```
206
226
 
207
- ```typescript
208
- interface User { name: string; }
227
+ Add to `package.json`:
209
228
 
210
- // Direct parameter return - no redundant validation
211
- function validate(user: User): User {
212
- return user; // Already validated on entry, skip return validation
229
+ ```json
230
+ {
231
+ "scripts": {
232
+ "build": "ttsc"
233
+ }
213
234
  }
235
+ ```
214
236
 
215
- // Property access from validated parameter
216
- function getAddress(user: User): Address {
217
- return user.address; // user was validated, address is safe
218
- }
237
+ ### Option 2: Manual tsconfig.json
238
+
239
+ Add to your `tsconfig.json`:
219
240
 
220
- // Type-annotated const
221
- function getUser(): User {
222
- const user: User = fetchData(); // const is validated here
223
- return user; // skip redundant validation
241
+ ```json
242
+ {
243
+ "compilerOptions": {
244
+ "plugins": [
245
+ {
246
+ "transform": "@elliots/typical-tsc-plugin",
247
+ "transformProgram": true
248
+ }
249
+ ]
250
+ }
224
251
  }
225
252
  ```
226
253
 
227
- ### When return validation IS applied (tainting):
254
+ Then run ts-patch's tsc:
228
255
 
229
- ```typescript
230
- // After mutation
231
- function updateUser(user: User): User {
232
- user.name = "modified"; // Mutation taints the value
233
- return user; // Must re-validate
234
- }
235
-
236
- // After passing to another function
237
- function processUser(user: User): User {
238
- someFunction(user); // Could have mutated user
239
- return user; // Must re-validate
240
- }
256
+ ```bash
257
+ npx ts-patch install
258
+ npx tsc
259
+ ```
241
260
 
242
- // After await (async boundary)
243
- async function asyncProcess(user: User): Promise<User> {
244
- await delay(); // Async boundary taints values
245
- return user; // Must re-validate
246
- }
261
+ Or add a prepare script:
247
262
 
248
- // Spread into new object
249
- function cloneUser(user: User): User {
250
- return { ...user }; // New object, must validate
263
+ ```json
264
+ {
265
+ "scripts": {
266
+ "prepare": "ts-patch install -s",
267
+ "build": "tsc"
268
+ }
251
269
  }
252
270
  ```
253
271
 
254
- ## Debugging
272
+ ---
255
273
 
256
- ### Intermediate Files
274
+ ## Configuration
257
275
 
258
- To see what code Typical generates before typia processes it, enable intermediate file output:
276
+ Create a `typical.json` file in your project root (optional):
259
277
 
260
278
  ```json
261
279
  {
262
- "debug": {
263
- "writeIntermediateFiles": true
264
- }
280
+ "include": ["**/*.ts", "**/*.tsx"],
281
+ "exclude": ["node_modules/**", "**/*.d.ts"],
282
+ "validateFunctions": true,
283
+ "validateCasts": false
265
284
  }
266
285
  ```
267
286
 
268
- This creates `.typical.ts` files alongside your output showing the code with typia calls injected but not yet transformed.
287
+ ### Options
269
288
 
270
- ### Verbose Logging
289
+ | Option | Default | Description |
290
+ | ------------------------ | --------------------------------------------------------- | ----------------------------------------------------------------- |
291
+ | `include` | `["**/*.ts", "**/*.tsx"]` | Files to transform |
292
+ | `exclude` | `["node_modules/**", "**/*.d.ts", "dist/**", "build/**"]` | Files to skip |
293
+ | `validateFunctions` | `true` | Validate function parameters and return types |
294
+ | `validateCasts` | `false` | Validate type assertions (`as Type`) |
295
+ | `transformJSONParse` | `true` | Transform `JSON.parse` to validate and filter to typed properties |
296
+ | `transformJSONStringify` | `true` | Transform `JSON.stringify` to only include typed properties |
271
297
 
272
- Set `DEBUG=1` environment variable for detailed logging:
298
+ ---
273
299
 
274
- ```bash
275
- DEBUG=1 npm run build
276
- ```
300
+ ## JSON Transformations
277
301
 
278
- ## Troubleshooting
302
+ Typical automatically transforms `JSON.parse` and `JSON.stringify` calls when type information is available.
279
303
 
280
- ### "Failed to transform the following types"
304
+ ### JSON.parse
281
305
 
282
- This error means typia couldn't generate validation code for certain types. Common causes:
306
+ When you cast the result of `JSON.parse`, Typical validates the parsed data and filters it to only include properties defined in your type:
283
307
 
284
- 1. **DOM types**: Types like `HTMLElement`, `Document`, etc. have complex intersections typia can't process.
285
- - Solution: Enable `ignoreDOMTypes: true` (default) or add specific types to `ignoreTypes`
308
+ ```ts
309
+ interface User {
310
+ name: string;
311
+ age: number;
312
+ }
286
313
 
287
- 2. **React types**: Event handlers, refs, and other React types often can't be validated.
288
- - Solution: Add `"React.*"` to `ignoreTypes`
314
+ // Input: '{"name":"Alice","age":30,"password":"secret"}'
315
+ const user = JSON.parse(jsonString) as User;
316
+ // Result: { name: "Alice", age: 30 } - password is filtered out!
317
+ // Throws TypeError if name isn't a string or age isn't a number
318
+ ```
289
319
 
290
- 3. **Third-party library types**: Some library types are too complex.
291
- - Solution: Add the specific type patterns to `ignoreTypes`
320
+ ### JSON.stringify
292
321
 
293
- ```json
294
- {
295
- "ignoreTypes": ["React.*", "Express.Request", "Prisma.*"]
322
+ When you use a type assertion with `JSON.stringify`, only properties defined in your type are included - preventing accidental data leaks:
323
+
324
+ ```ts
325
+ interface PublicUser {
326
+ name: string;
327
+ age: number;
296
328
  }
329
+
330
+ const user = { name: "Alice", age: 30, password: "secret", ssn: "123-45-6789" };
331
+ const json = JSON.stringify(user as PublicUser);
332
+ // Result: '{"name":"Alice","age":30}' - sensitive data excluded!
297
333
  ```
298
334
 
299
- ### "Window & typeof globalThis" errors
335
+ Both patterns detect type information from:
300
336
 
301
- This occurs when a type includes DOM globals. Enable `ignoreDOMTypes: true` or add the specific type to `ignoreTypes`.
337
+ - Type assertions: `JSON.parse(str) as User` or `JSON.stringify(obj as User)`
338
+ - Variable declarations: `const user: User = JSON.parse(str)`
339
+ - Function return types: `function getUser(): User { return JSON.parse(str) }`
302
340
 
303
- ### Generic type parameters not validated
341
+ ---
304
342
 
305
- Type parameters (`T`, `U`, etc.) cannot be validated at runtime because the actual type isn't known until the function is called. This is by design:
343
+ ## How It Works
306
344
 
307
- ```typescript
308
- function identity<T>(value: T): T {
309
- return value; // T is not validated - no runtime type info
310
- }
311
- ```
345
+ Typical uses a Go-based compiler that leverages the TypeScript type checker to analyze your code. It generates runtime validators that check values against their declared types.
312
346
 
313
- Concrete types in the same function ARE validated:
347
+ Types that can't be validated at runtime (like generic type parameters `T`) are skipped. You can still use `any` and `unknown` to opt out of validation.
314
348
 
315
- ```typescript
316
- function process<T>(value: T, user: User): User {
317
- return user; // User IS validated
318
- }
319
- ```
349
+ ## Compiler Optimizations
320
350
 
321
- ### Constructor parameters not validated
351
+ The generated validation code is optimized for runtime performance:
322
352
 
323
- Currently, class constructors are not transformed. This is a known limitation. Validate in the constructor body if needed:
353
+ - **Skip redundant validation** - When returning a validated parameter directly, the return validation is skipped (e.g., `return x` where `x: string` was already validated)
354
+ - **Subtype-aware skipping** - If a validated type is assignable to the return type, validation is skipped (e.g., `string` parameter returned as `string | null`)
355
+ - **Property chain tracking** - Accessing properties of validated objects skips re-validation (e.g., `return user.name` when `user: User` was validated)
356
+ - **Type-aware dirty tracking** - Primitives stay validated after being passed to functions (they're copied), but objects are re-validated (they could be mutated)
357
+ - **Union early bail-out** - Union type checks use if-else chains so the first matching type succeeds immediately
324
358
 
325
- ```typescript
326
- class Client {
327
- constructor(options: Options) {
328
- // Manual validation if needed
329
- if (!options.timeout) throw new Error("timeout required");
330
- }
331
- }
332
- ```
359
+ ## Debugging
360
+
361
+ Set `DEBUG=1` for verbose logging:
333
362
 
334
- ## Credits
335
- The actual validation work is done by [typia](https://github.com/samchon/typia). This package just generates the necessary code to call typia's functions based on your TypeScript types.
363
+ ```bash
364
+ DEBUG=1 npm run build
365
+ ```
336
366
 
337
- > NOTE: The whole package was all mostly LLM. Feel free to improve it without care for the author's feelings.
367
+ ## Limitations
338
368
 
369
+ - Generic type parameters (`T`) cannot be validated - no runtime type information
370
+ - Type-only imports of classes aren't checked (can't do instanceof on type-only imports)
371
+ - Validation of functions is just not done. Need to think about that one.
372
+ - Some complex types may not be fully supported yet. If you find any that fail, please open an issue!