TypeScript runtime type system for IO decoding/encoding
72
Error reporting interfaces and implementations for converting validation failures into human-readable messages.
Base interface for error reporting implementations.
/**
* Generic interface for converting validation results to custom output formats
* @template A - Output type for the reporter
*/
interface Reporter<A> {
/** Function that processes validation results and returns formatted output */
report: (validation: Validation<any>) => A;
}The main error reporter that converts validation errors to readable string messages with path information.
/**
* Reporter that converts validation errors to an array of error messages
*/
const PathReporter: Reporter<Array<string>>;
/**
* Convert validation errors to string messages
* @param es - Array of validation errors
* @returns Array of formatted error messages
*/
function failure(es: Array<ValidationError>): Array<string>;
/**
* Generate success message
* @returns Array containing success message
*/
function success(): Array<string>;Usage Examples:
import * as t from "io-ts";
import { PathReporter } from "io-ts/PathReporter";
const User = t.type({
name: t.string,
age: t.number
});
// Valid data
const validResult = User.decode({ name: "Alice", age: 30 });
console.log(PathReporter.report(validResult));
// Output: ["No errors!"]
// Invalid data
const invalidResult = User.decode({ name: 42, age: "thirty" });
console.log(PathReporter.report(invalidResult));
// Output: [
// "Invalid value 42 supplied to name: string",
// "Invalid value \"thirty\" supplied to age: number"
// ]
// Complex nested validation
const Address = t.type({
street: t.string,
city: t.string,
zipCode: t.string
});
const Person = t.type({
name: t.string,
address: Address
});
const result = Person.decode({
name: "John",
address: { street: 123, city: "NYC" } // missing zipCode, invalid street
});
console.log(PathReporter.report(result));
// Output: [
// "Invalid value 123 supplied to address/street: string",
// "Invalid value undefined supplied to address/zipCode: string"
// ]⚠️ DEPRECATED: Use PathReporter instead for better error handling.
/**
* @deprecated Use PathReporter instead
* Reporter that throws errors instead of returning them
*/
const ThrowReporter: Reporter<void>;Migration Example:
// ❌ Don't use ThrowReporter (deprecated)
import { ThrowReporter } from "io-ts/ThrowReporter";
try {
ThrowReporter.report(result);
} catch (error) {
console.error(error.message);
}
// ✅ Use PathReporter instead
import { PathReporter } from "io-ts/PathReporter";
import { isLeft } from "fp-ts/Either";
if (isLeft(result)) {
const errors = PathReporter.report(result);
console.error(errors.join('\n'));
}import * as t from "io-ts";
import { fold } from "fp-ts/Either";
import { Reporter } from "io-ts/Reporter";
// Custom reporter that returns structured error objects
interface StructuredError {
field: string;
value: unknown;
expected: string;
message: string;
}
const StructuredReporter: Reporter<StructuredError[]> = {
report: fold(
(errors) => errors.map(error => ({
field: error.context.map(c => c.key).filter(Boolean).join('.'),
value: error.value,
expected: error.context[error.context.length - 1]?.type.name || 'unknown',
message: error.message || `Expected ${error.context[error.context.length - 1]?.type.name}`
})),
() => []
)
};
// Usage
const result = t.string.decode(42);
const structuredErrors = StructuredReporter.report(result);
console.log(structuredErrors);
// Output: [{
// field: "",
// value: 42,
// expected: "string",
// message: "Expected string"
// }]import { fold } from "fp-ts/Either";
import { Reporter } from "io-ts/Reporter";
const JSONReporter: Reporter<string> = {
report: fold(
(errors) => JSON.stringify({
success: false,
errors: errors.map(e => ({
path: e.context.map(c => c.key).filter(Boolean).join('.'),
value: e.value,
message: e.message || `Invalid value supplied`
}))
}, null, 2),
(value) => JSON.stringify({ success: true, data: value }, null, 2)
)
};import * as t from "io-ts";
import { PathReporter } from "io-ts/PathReporter";
import { pipe } from "fp-ts/function";
import { fold } from "fp-ts/Either";
const validateAndLog = <A>(codec: t.Type<A>, data: unknown): A | null => {
return pipe(
codec.decode(data),
fold(
(errors) => {
const errorMessages = PathReporter.report(codec.decode(data));
console.error('Validation failed:', errorMessages);
return null;
},
(valid) => {
console.log('Validation successful');
return valid;
}
)
);
};PathReporter generates error messages in the format:
"Invalid value <value> supplied to <path>"parent/child/grandchildPath Examples:
"Invalid value 42 supplied to : string""Invalid value null supplied to name: string""Invalid value 123 supplied to address/street: string""Invalid value "invalid" supplied to items/0: number"Install with Tessl CLI
npx tessl i tessl/npm-io-tsdocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10