ts-fortress 4.1.1 → 4.1.2

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 (2) hide show
  1. package/README.md +108 -0
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -291,6 +291,114 @@ user.tags.push('new tag'); // No error
291
291
  user.tags[0] = 'modified'; // No error
292
292
  ```
293
293
 
294
+ **In io-ts, Readonly types will generate verbose error messages**:
295
+
296
+ ```typescript
297
+ import * as ioTs from 'io-ts';
298
+ import { PathReporter } from 'io-ts/PathReporter';
299
+
300
+ // io-ts nested readonly version with multiple Readonly wrappers
301
+ const IoTsNestedReadonly = ioTs.readonly(
302
+ ioTs.type({
303
+ user: ioTs.readonly(
304
+ ioTs.type({
305
+ profile: ioTs.readonly(
306
+ ioTs.type({
307
+ age: ioTs.number,
308
+ }),
309
+ ),
310
+ }),
311
+ ),
312
+ }),
313
+ );
314
+
315
+ const invalidData = {
316
+ user: {
317
+ profile: {
318
+ age: 'not-a-number', // should be number
319
+ },
320
+ },
321
+ };
322
+
323
+ // Get io-ts error messages
324
+ const ioTsResult = IoTsNestedReadonly.decode(invalidData);
325
+ const ioTsErrorMessages = PathReporter.report(ioTsResult);
326
+
327
+ console.log(ioTsErrorMessages[0]);
328
+ // Output: Invalid value "not-a-number" supplied to : Readonly<{ user: Readonly<{ profile: Readonly<{ age: number }> }> }>/user: Readonly<{ profile: Readonly<{ age: number }> }>/profile: Readonly<{ age: number }>/age: number
329
+ ```
330
+
331
+ **The error message contains excessive `Readonly<...>` wrapper noise:**
332
+
333
+ - Root level: `Readonly<{ user: Readonly<{ profile: Readonly<{ age: number }> }> }>`
334
+ - User level: `Readonly<{ profile: Readonly<{ age: number }> }>`
335
+ - Profile level: `Readonly<{ age: number }>`
336
+ - Each nested readonly creates exponentially verbose error messages with redundant type information
337
+
338
+ This verbosity makes error messages extremely difficult to read and debug in production environments.
339
+
340
+ **ts-fortress addresses this issue** by generating clean, actionable error messages without verbose type wrapper details:
341
+
342
+ ```typescript
343
+ import * as tf from 'ts-fortress';
344
+
345
+ // ts-fortress equivalent clean structure
346
+ const TsFortressNestedType = tf.record({
347
+ user: tf.record({
348
+ profile: tf.record({
349
+ age: tf.number(0),
350
+ }),
351
+ }),
352
+ });
353
+
354
+ // Get ts-fortress error messages
355
+ const tsFortressResult = TsFortressNestedType.validate(invalidData);
356
+ const tsFortressErrorMessages = tf.Result.isErr(tsFortressResult)
357
+ ? tf.validationErrorsToMessages(tsFortressResult.value)
358
+ : [];
359
+
360
+ console.log(tsFortressErrorMessages[0]);
361
+ // Clean output: Expected <number> at user.profile.age, got <string> type value "not-a-number".
362
+ ```
363
+
364
+ **ts-fortress vs zod comparison:**
365
+
366
+ ```typescript
367
+ import { z } from 'zod';
368
+
369
+ // zod nested readonly equivalent
370
+ const ZodNestedType = z
371
+ .object({
372
+ user: z
373
+ .object({
374
+ profile: z
375
+ .object({
376
+ age: z.number(),
377
+ })
378
+ .readonly(),
379
+ })
380
+ .readonly(),
381
+ })
382
+ .readonly();
383
+
384
+ // Get zod error messages using prettifyError
385
+ const zodResult = ZodNestedType.safeParse(invalidData);
386
+ const zodErrorMessages = zodResult.success
387
+ ? ''
388
+ : z.prettifyError(zodResult.error);
389
+
390
+ console.log(zodErrorMessages);
391
+ // Clean output: "✖ Invalid input: expected number, received string\n → at user.profile.age"
392
+ ```
393
+
394
+ **Error message comparison:**
395
+
396
+ - **io-ts**: 148 characters of verbose type information mixed with the actual error
397
+ - **zod**: 62 characters with visual formatting but missing the actual invalid value
398
+ - **ts-fortress**: 74 characters focused purely on what went wrong and where, including the actual invalid value
399
+
400
+ While zod produces cleaner error messages than io-ts and includes helpful visual formatting, **ts-fortress provides superior debugging experience** by including the actual invalid value (`"not-a-number"`) in the error message, making it easier to understand what data caused the validation failure.
401
+
294
402
  ### Benefits of Deep Readonly
295
403
 
296
404
  - **Immutability by default**: Prevents accidental mutations that can lead to bugs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-fortress",
3
- "version": "4.1.1",
3
+ "version": "4.1.2",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "typescript"