typia
Version:
Superfast runtime validators with only one line
147 lines (132 loc) • 4.19 kB
text/typescript
/**
* Error thrown when type assertion fails.
*
* Thrown by {@link assert}, {@link assertGuard}, and other assert-family
* functions when input doesn't match expected type `T`. Contains detailed
* information about the first assertion failure:
*
* - `method`: Which typia function threw (e.g., `"typia.assert"`)
* - `path`: Property path where error occurred (e.g., `"input.user.age"`)
* - `expected`: Expected type string (e.g., `"number & ExclusiveMinimum<19>"`)
* - `value`: Actual value that failed validation
*
* @template T Expected type (for type safety)
*/
export class TypeGuardError<T = any> extends Error {
/**
* Name of the typia method that threw this error.
*
* E.g., `"typia.assert"`, `"typia.assertEquals"`, `"typia.assertGuard"`.
*/
public readonly method: string;
/**
* Property path where assertion failed.
*
* Uses dot notation for nested properties. `undefined` if error occurred at
* root level.
*
* E.g., `"input.age"`, `"input.profile.email"`, `"input[0].name"`.
*/
public readonly path: string | undefined;
/**
* String representation of expected type.
*
* E.g., `"string"`, `"number & ExclusiveMinimum<19>"`, `"{ name: string; age:
* number }"`.
*/
public readonly expected: string;
/**
* Actual value that failed assertion.
*
* The raw value at the error path, useful for debugging.
*/
public readonly value: unknown;
/**
* Optional human-readable error description.
*
* Primarily for AI agent libraries or custom validation scenarios needing
* additional context. Standard assertions rely on `path`, `expected`, and
* `value` for error reporting.
*/
public readonly description?: string | undefined;
/**
* Phantom property for TypeScript type safety.
*
* Not used at runtime—exists only to preserve generic type `T` in the type
* system. Always `undefined`.
*
* @internal
*/
protected readonly fake_expected_typed_value_?: T | undefined;
/**
* Creates a new TypeGuardError instance.
*
* @param props Error properties
*/
public constructor(props: TypeGuardError.IProps) {
// MESSAGE CONSTRUCTION
// Use custom message if provided, otherwise generate default format
super(
props.message ||
`Error on ${props.method}(): invalid type${
props.path ? ` on ${props.path}` : ""
}, expect to be ${props.expected}`,
);
// INHERITANCE POLYFILL
// Set up prototype for compatibility across different JavaScript environments
const proto = new.target.prototype;
if (Object.setPrototypeOf) Object.setPrototypeOf(this, proto);
else (this as any).__proto__ = proto;
// ASSIGN MEMBERS
this.name = "TypeGuardError";
this.method = props.method;
this.path = props.path;
this.expected = props.expected;
this.value = props.value;
if (props.description || props.value === undefined)
this.description =
props.description ??
[
"The value at this path is `undefined`.",
"",
`Please fill the \`${props.expected}\` typed value next time.`,
].join("\n");
}
}
export namespace TypeGuardError {
/** Properties for constructing a TypeGuardError. */
export interface IProps {
/**
* Name of the typia method that threw the error.
*
* E.g., `"typia.assert"`, `"typia.assertEquals"`.
*/
method: string;
/**
* Property path where assertion failed (optional).
*
* E.g., `"input.age"`, `"input.profile.email"`.
*/
path?: undefined | string;
/**
* String representation of expected type.
*
* E.g., `"string"`, `"number & ExclusiveMinimum<19>"`.
*/
expected: string;
/** Actual value that failed assertion. */
value: unknown;
/**
* Optional human-readable error description.
*
* For AI agent libraries or custom validation needing additional context.
*/
description?: string;
/**
* Custom error message (optional).
*
* If not provided, a default message is generated from other properties.
*/
message?: undefined | string;
}
}