0
# Error Reporting System
1
2
Error reporting interfaces and implementations for converting validation failures into human-readable messages.
3
4
## Capabilities
5
6
### Reporter Interface
7
8
Base interface for error reporting implementations.
9
10
```typescript { .api }
11
/**
12
* Generic interface for converting validation results to custom output formats
13
* @template A - Output type for the reporter
14
*/
15
interface Reporter<A> {
16
/** Function that processes validation results and returns formatted output */
17
report: (validation: Validation<any>) => A;
18
}
19
```
20
21
### PathReporter
22
23
The main error reporter that converts validation errors to readable string messages with path information.
24
25
```typescript { .api }
26
/**
27
* Reporter that converts validation errors to an array of error messages
28
*/
29
const PathReporter: Reporter<Array<string>>;
30
31
/**
32
* Convert validation errors to string messages
33
* @param es - Array of validation errors
34
* @returns Array of formatted error messages
35
*/
36
function failure(es: Array<ValidationError>): Array<string>;
37
38
/**
39
* Generate success message
40
* @returns Array containing success message
41
*/
42
function success(): Array<string>;
43
```
44
45
**Usage Examples:**
46
47
```typescript
48
import * as t from "io-ts";
49
import { PathReporter } from "io-ts/PathReporter";
50
51
const User = t.type({
52
name: t.string,
53
age: t.number
54
});
55
56
// Valid data
57
const validResult = User.decode({ name: "Alice", age: 30 });
58
console.log(PathReporter.report(validResult));
59
// Output: ["No errors!"]
60
61
// Invalid data
62
const invalidResult = User.decode({ name: 42, age: "thirty" });
63
console.log(PathReporter.report(invalidResult));
64
// Output: [
65
// "Invalid value 42 supplied to name: string",
66
// "Invalid value \"thirty\" supplied to age: number"
67
// ]
68
69
// Complex nested validation
70
const Address = t.type({
71
street: t.string,
72
city: t.string,
73
zipCode: t.string
74
});
75
76
const Person = t.type({
77
name: t.string,
78
address: Address
79
});
80
81
const result = Person.decode({
82
name: "John",
83
address: { street: 123, city: "NYC" } // missing zipCode, invalid street
84
});
85
86
console.log(PathReporter.report(result));
87
// Output: [
88
// "Invalid value 123 supplied to address/street: string",
89
// "Invalid value undefined supplied to address/zipCode: string"
90
// ]
91
```
92
93
### ThrowReporter (Deprecated)
94
95
**⚠️ DEPRECATED:** Use PathReporter instead for better error handling.
96
97
```typescript { .api }
98
/**
99
* @deprecated Use PathReporter instead
100
* Reporter that throws errors instead of returning them
101
*/
102
const ThrowReporter: Reporter<void>;
103
```
104
105
**Migration Example:**
106
107
```typescript
108
// ❌ Don't use ThrowReporter (deprecated)
109
import { ThrowReporter } from "io-ts/ThrowReporter";
110
111
try {
112
ThrowReporter.report(result);
113
} catch (error) {
114
console.error(error.message);
115
}
116
117
// ✅ Use PathReporter instead
118
import { PathReporter } from "io-ts/PathReporter";
119
import { isLeft } from "fp-ts/Either";
120
121
if (isLeft(result)) {
122
const errors = PathReporter.report(result);
123
console.error(errors.join('\n'));
124
}
125
```
126
127
## Advanced Usage
128
129
### Custom Reporter Implementation
130
131
```typescript
132
import * as t from "io-ts";
133
import { fold } from "fp-ts/Either";
134
import { Reporter } from "io-ts/Reporter";
135
136
// Custom reporter that returns structured error objects
137
interface StructuredError {
138
field: string;
139
value: unknown;
140
expected: string;
141
message: string;
142
}
143
144
const StructuredReporter: Reporter<StructuredError[]> = {
145
report: fold(
146
(errors) => errors.map(error => ({
147
field: error.context.map(c => c.key).filter(Boolean).join('.'),
148
value: error.value,
149
expected: error.context[error.context.length - 1]?.type.name || 'unknown',
150
message: error.message || `Expected ${error.context[error.context.length - 1]?.type.name}`
151
})),
152
() => []
153
)
154
};
155
156
// Usage
157
const result = t.string.decode(42);
158
const structuredErrors = StructuredReporter.report(result);
159
console.log(structuredErrors);
160
// Output: [{
161
// field: "",
162
// value: 42,
163
// expected: "string",
164
// message: "Expected string"
165
// }]
166
```
167
168
### JSON Reporter
169
170
```typescript
171
import { fold } from "fp-ts/Either";
172
import { Reporter } from "io-ts/Reporter";
173
174
const JSONReporter: Reporter<string> = {
175
report: fold(
176
(errors) => JSON.stringify({
177
success: false,
178
errors: errors.map(e => ({
179
path: e.context.map(c => c.key).filter(Boolean).join('.'),
180
value: e.value,
181
message: e.message || `Invalid value supplied`
182
}))
183
}, null, 2),
184
(value) => JSON.stringify({ success: true, data: value }, null, 2)
185
)
186
};
187
```
188
189
### Integration with Logging
190
191
```typescript
192
import * as t from "io-ts";
193
import { PathReporter } from "io-ts/PathReporter";
194
import { pipe } from "fp-ts/function";
195
import { fold } from "fp-ts/Either";
196
197
const validateAndLog = <A>(codec: t.Type<A>, data: unknown): A | null => {
198
return pipe(
199
codec.decode(data),
200
fold(
201
(errors) => {
202
const errorMessages = PathReporter.report(codec.decode(data));
203
console.error('Validation failed:', errorMessages);
204
return null;
205
},
206
(valid) => {
207
console.log('Validation successful');
208
return valid;
209
}
210
)
211
);
212
};
213
```
214
215
## Error Message Format
216
217
PathReporter generates error messages in the format:
218
- **Path-based errors:** `"Invalid value <value> supplied to <path>"`
219
- **Custom message errors:** Uses the custom message if provided
220
- **Complex paths:** Nested paths shown as `parent/child/grandchild`
221
222
**Path Examples:**
223
- Root level: `"Invalid value 42 supplied to : string"`
224
- Object property: `"Invalid value null supplied to name: string"`
225
- Nested object: `"Invalid value 123 supplied to address/street: string"`
226
- Array element: `"Invalid value "invalid" supplied to items/0: number"`
227
- Union types: Shows attempted matches with context