parse()
functions
undefined
export namespace json {
export function isParse<T>(input: string): Primitive<T> | null;
export function assertParse<T>(input: string): Primitive<T>;
export function validateParse<T>(input: string): IValidation<Primitive<T>>;
}
undefined
/**
* Custom error class thrown when runtime assertion fails in `typia.assert<T>()` function.
*
* This error is thrown by the `typia.assert<T>()` function when the input value
* doesn't match the expected type.
*
* The error provides detailed information about the first assertion failure encountered,
* including the access path where the error occurred, the expected type, and the actual value.
*
* @template T - The expected type (generic for type safety)
* @author Jeongho Nam - https://github.com/samchon
* @example
* ```typescript
* interface IMember {
* name: string;
* age: number & ExclusiveMinimum<19>;
* }
*
* try {
* typia.assert<IMember>({ name: "John", age: 18 });
* } catch (error) {
* if (error instanceof TypeGuardError) {
* console.log(error.method); // "typia.assert"
* console.log(error.path); // "input.age"
* console.log(error.expected); // "number & ExclusiveMinimum<19>"
* console.log(error.value); // 18
* }
* }
* ```
*/
export class TypeGuardError<T = any> extends Error {
/**
* The name of the typia method that threw this error.
*
* @example "typia.assert"
*/
public readonly method: string;
/**
* The access path to the property where the assertion error occurred.
*
* Uses dot notation to indicate the path for nested object properties.
* May be `undefined` if the error occurred at the root level.
*
* @example
* - `"input.age"` - Error in the age property of the object
* - `"input.profile.email"` - Error in the email property of a nested object
* - `"input[0].name"` - Error in the name property of the first array element
* - `undefined` - Error occurred at the root level
*/
public readonly path: string | undefined;
/**
* String representation of the expected type at the error location.
*
* Represents TypeScript types as strings, including detailed type information
* for complex types.
*
* @example
* - `"string"` - Expected string type
* - `"number & ExclusiveMinimum<19>"` - Expected number greater than 19
* - `"undefined"` - Expected undefined (when superfluous property found in assertion)
* - `"{ name: string; age: number }"` - Expected object type
*/
public readonly expected: string;
/**
* The actual value that failed assertion.
*
* Stores the actual value at the error path as-is.
* Useful for debugging by comparing the expected type with the actual value.
*
* @example
* - `18` - Numeric value
* - `"invalid"` - String value
* - `{ name: "John", age: 18, sex: 1 }` - Object value
*/
public readonly value: any;
/**
* Phantom property for type safety purposes.
*
* This property is not actually used and exists only to maintain
* the generic type T in TypeScript's type system.
* Always has an `undefined` value at runtime.
*
* @internal
*/
protected readonly fake_expected_typed_value_?: T | undefined;
/**
* Creates a new TypeGuardError instance.
*
* @param props - Object containing the properties needed to create the error
*
* @example
* ```typescript
* const error = new TypeGuardError({
* method: "typia.assert",
* path: "input.age",
* expected: "number & ExclusiveMinimum<19>",
* value: 18
* });
* ```
*/
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.method = props.method;
this.path = props.path;
this.expected = props.expected;
this.value = props.value;
}
}
export namespace TypeGuardError {
/**
* Interface for properties passed to the TypeGuardError constructor.
*
* @example
* ```typescript
* const props: TypeGuardError.IProps = {
* method: "typia.assertEquals",
* path: "input.sex",
* expected: "undefined",
* value: 1,
* message: "Custom error message" // optional
* };
* ```
*/
export interface IProps {
/**
* The name of the typia method that threw the error.
*
* @example "typia.assert", "typia.assertEquals"
*/
method: string;
/**
* The access path to the property where the assertion error occurred (optional).
*
* @example "input.age", "input.profile.email"
*/
path?: undefined | string;
/**
* String representation of the expected type at the error location.
*
* @example "string", "number & ExclusiveMinimum<19>"
*/
expected: string;
/**
* The actual value that failed assertion.
*/
value: any;
/**
* Custom error message (optional).
*
* If not provided, a default format message will be automatically generated.
*/
message?: undefined | string;
}
}
undefined
/**
* Union type representing the result of type validation
*
* This is the return type of {@link typia.validate} functions, returning
* {@link IValidation.ISuccess} on validation success and
* {@link IValidation.IFailure} on validation failure. When validation fails, it
* provides detailed, granular error information that precisely describes what
* went wrong, where it went wrong, and what was expected.
*
* This comprehensive error reporting makes `IValidation` particularly valuable
* for AI function calling scenarios, where Large Language Models (LLMs) need
* specific feedback to correct their parameter generation. The detailed error
* information is used by ILlmFunction.validate() to provide validation feedback
* to AI agents, enabling iterative correction and improvement of function
* calling accuracy.
*
* This type uses the Discriminated Union pattern, allowing type specification
* through the success property:
*
* ```typescript
* const result = typia.validate<string>(input);
* if (result.success) {
* // IValidation.ISuccess<string> type
* console.log(result.data); // validated data accessible
* } else {
* // IValidation.IFailure type
* console.log(result.errors); // detailed error information accessible
* }
* ```
*
* @author Jeongho Nam - https://github.com/samchon
* @template T The type to validate
*/
export type IValidation<T = unknown> =
| IValidation.ISuccess<T>
| IValidation.IFailure;
export namespace IValidation {
/**
* Interface returned when type validation succeeds
*
* Returned when the input value perfectly conforms to the specified type T.
* Since success is true, TypeScript's type guard allows safe access to the
* validated data through the data property.
*
* @template T The validated type
*/
export interface ISuccess<T = unknown> {
/** Indicates validation success */
success: true;
/** The validated data of type T */
data: T;
}
/**
* Interface returned when type validation fails
*
* Returned when the input value does not conform to the expected type.
* Contains comprehensive error information designed to be easily understood
* by both humans and AI systems. Each error in the errors array provides
* precise details about validation failures, including the exact path to the
* problematic property, what type was expected, and what value was actually
* provided.
*
* This detailed error structure is specifically optimized for AI function
* calling validation feedback. When LLMs make type errors during function
* calling, these granular error reports enable the AI to understand exactly
* what went wrong and how to fix it, improving success rates in subsequent
* attempts.
*
* Example error scenarios:
*
* - Type mismatch: expected "string" but got number 5
* - Format violation: expected "string & Format<'uuid'>" but got
* "invalid-format"
* - Missing properties: expected "required property 'name'" but got undefined
* - Array type errors: expected "Array<string>" but got single string value
*
* The errors are used by ILlmFunction.validate() to provide structured
* feedback to AI agents, enabling them to correct their parameter generation
* and achieve improved function calling accuracy.
*/
export interface IFailure {
/** Indicates validation failure */
success: false;
/** The original input data that failed validation */
data: unknown;
/** Array of detailed validation errors */
errors: IError[];
}
/**
* Detailed information about a specific validation error
*
* Each error provides granular, actionable information about validation
* failures, designed to be immediately useful for both human developers and
* AI systems. The error structure follows a consistent format that enables
* precise identification and correction of type mismatches.
*
* This error format is particularly valuable for AI function calling
* scenarios, where LLMs need to understand exactly what went wrong to
* generate correct parameters. The combination of path, expected type, and
* actual value provides the AI with sufficient context to make accurate
* corrections, which is why ILlmFunction.validate() can achieve such high
* success rates in validation feedback loops.
*
* Real-world examples from AI function calling:
*
* {
* path: "input.member.age",
* expected: "number & Format<'uint32'>",
* value: 20.75 // AI provided float instead of uint32
* }
*
* {
* path: "input.categories",
* expected: "Array<string>",
* value: "technology" // AI provided string instead of array
* }
*
* {
* path: "input.id",
* expected: "string & Format<'uuid'>",
* value: "invalid-uuid-format" // AI provided malformed UUID
* }
*/
export interface IError {
/**
* The path to the property that failed validation (e.g.,
* "input.member.age")
*/
path: string;
/** Description of the expected type or format */
expected: string;
/** The actual value that caused the validation failure */
value: any;
}
}
undefined
import { Equal } from "./typings/Equal";
import { IsTuple } from "./typings/IsTuple";
import { NativeClass } from "./typings/NativeClass";
import { ValueOf } from "./typings/ValueOf";
import { Format } from "./tags";
/**
* Primitive type of JSON.
*
* `Primitive<T>` is a TMP (Type Meta Programming) type which converts
* its argument as a primitive type within framework JSON.
*
* If the target argument is a built-in class which returns its origin primitive type
* through the `valueOf()` method like the `String` or `Number`, its return type would
* be the `string` or `number`. Otherwise, the built-in class does not have the
* `valueOf()` method, the return type would be an empty object (`{}`).
*
* Otherwise, the target argument is a type of custom class, all of its custom method
* would be erased and its prototype would be changed to the primitive `object`.
* Therefore, return type of the TMP type finally be the primitive object.
*
* In addition, if the target argument is a type of custom class and it has a special
* method `toJSON()`, return type of this `Primitive` would be not `Primitive<Instance>`
* but `Primitive<ReturnType<Instance.toJSON>>`.
*
* Before | After
* ------------------------|----------------------------------------
* `Boolean` | `boolean`
* `Number` | `number`
* `String` | `string`
* `Class` | `object`
* `Class` with `toJSON()` | `Primitive<ReturnType<Class.toJSON>>`
* Native Class | never
* Others | No change
*
* @template T Target argument type.
* @author Jeongho Nam - https://github.com/samchon
* @author Kyungsu Kang - https://github.com/kakasoo
* @author Michael - https://github.com/8471919
*/
export type Primitive<T> =
Equal<T, PrimitiveMain<T>> extends true ? T : PrimitiveMain<T>;
type PrimitiveMain<Instance> = Instance extends [never]
? never // (special trick for jsonable | null) type
: ValueOf<Instance> extends bigint
? never
: ValueOf<Instance> extends boolean | number | string
? ValueOf<Instance>
: Instance extends Function
? never
: ValueOf<Instance> extends object
? Instance extends object
? Instance extends Date
? string & Format<"date-time">
: Instance extends IJsonable<infer Raw>
? ValueOf<Raw> extends object
? Raw extends object
? PrimitiveObject<Raw> // object would be primitified
: never // cannot be
: ValueOf<Raw> // atomic value
: Instance extends Exclude<NativeClass, Date>
? never
: PrimitiveObject<Instance> // object would be primitified
: never // cannot be
: ValueOf<Instance>;
type PrimitiveObject<Instance extends object> =
Instance extends Array<infer T>
? IsTuple<Instance> extends true
? PrimitiveTuple<Instance>
: PrimitiveMain<T>[]
: {
[P in keyof Instance]: PrimitiveMain<Instance[P]>;
};
type PrimitiveTuple<T extends readonly any[]> = T extends []
? []
: T extends [infer F]
? [PrimitiveMain<F>]
: T extends [infer F, ...infer Rest extends readonly any[]]
? [PrimitiveMain<F>, ...PrimitiveTuple<Rest>]
: T extends [(infer F)?]
? [PrimitiveMain<F>?]
: T extends [(infer F)?, ...infer Rest extends readonly any[]]
? [PrimitiveMain<F>?, ...PrimitiveTuple<Rest>]
: [];
interface IJsonable<T> {
toJSON(): T;
}
Type safe JSON parser.
Unlike native JSON.parse()
function which returns any typed instance without type checking, typia.json.assertParse<T>()
function validates instance type after the parsing. If the parsed value is not following the promised type T
, it throws TypeGuardError
with the first type error info.
If you want to know every type error infos detaily, you can use typia.json.validateParse<T>()
function instead. Otherwise, you just only want to know whether the parsed value is following the type T
or not, just call typia.json.isParse<T>()
function.
typia.json.isParse<T>()
:JSON.parse()
+typia.is<T>()
typia.json.assertParse<T>()
:JSON.parse()
+typia.assert<T>()
typia.json.validateParse<T>()
:JSON.parse()
+typia.validate<T>()
Look at the below code, then you may understand how the typia.json.assertParse<T>()
function works.
TypeScript Source Code
import typia, { tags } from "typia";
const json: string = JSON.stringify(typia.random<IMember>());
const parsed: IMember = typia.json.assertParse<IMember>(json);
console.log(json === JSON.stringify(parsed)); // true
interface IMember {
id: string & tags.Format<"uuid">;
email: string & tags.Format<"email">;
age: number &
tags.Type<"uint32"> &
tags.ExclusiveMinimum<19> &
tags.Maximum<100>;
}
Compiled JavaScript File
import typia from "typia";
import * as __typia_transform__assertGuard from "typia/lib/internal/_assertGuard.js";
import * as __typia_transform__isFormatEmail from "typia/lib/internal/_isFormatEmail.js";
import * as __typia_transform__isFormatUuid from "typia/lib/internal/_isFormatUuid.js";
import * as __typia_transform__isTypeUint32 from "typia/lib/internal/_isTypeUint32.js";
import * as __typia_transform__randomFormatEmail from "typia/lib/internal/_randomFormatEmail.js";
import * as __typia_transform__randomFormatUuid from "typia/lib/internal/_randomFormatUuid.js";
import * as __typia_transform__randomInteger from "typia/lib/internal/_randomInteger.js";
const json = JSON.stringify(
(() => {
const _ro0 = (_recursive = false, _depth = 0) => ({
id: (
_generator?.uuid ??
__typia_transform__randomFormatUuid._randomFormatUuid
)(),
email: (
_generator?.email ??
__typia_transform__randomFormatEmail._randomFormatEmail
)(),
age: (
_generator?.integer ?? __typia_transform__randomInteger._randomInteger
)({
type: "integer",
minimum: 0,
exclusiveMinimum: 19,
maximum: 100,
}),
});
let _generator;
return (generator) => {
_generator = generator;
return _ro0();
};
})()(),
);
const parsed = (() => {
const _io0 = (input) =>
"string" === typeof input.id &&
__typia_transform__isFormatUuid._isFormatUuid(input.id) &&
"string" === typeof input.email &&
__typia_transform__isFormatEmail._isFormatEmail(input.email) &&
"number" === typeof input.age &&
__typia_transform__isTypeUint32._isTypeUint32(input.age) &&
19 < input.age &&
input.age <= 100;
const _ao0 = (input, _path, _exceptionable = true) =>
(("string" === typeof input.id &&
(__typia_transform__isFormatUuid._isFormatUuid(input.id) ||
__typia_transform__assertGuard._assertGuard(
_exceptionable,
{
method: "typia.json.assertParse",
path: _path + ".id",
expected: 'string & Format<"uuid">',
value: input.id,
},
_errorFactory,
))) ||
__typia_transform__assertGuard._assertGuard(
_exceptionable,
{
method: "typia.json.assertParse",
path: _path + ".id",
expected: '(string & Format<"uuid">)',
value: input.id,
},
_errorFactory,
)) &&
(("string" === typeof input.email &&
(__typia_transform__isFormatEmail._isFormatEmail(input.email) ||
__typia_transform__assertGuard._assertGuard(
_exceptionable,
{
method: "typia.json.assertParse",
path: _path + ".email",
expected: 'string & Format<"email">',
value: input.email,
},
_errorFactory,
))) ||
__typia_transform__assertGuard._assertGuard(
_exceptionable,
{
method: "typia.json.assertParse",
path: _path + ".email",
expected: '(string & Format<"email">)',
value: input.email,
},
_errorFactory,
)) &&
(("number" === typeof input.age &&
(__typia_transform__isTypeUint32._isTypeUint32(input.age) ||
__typia_transform__assertGuard._assertGuard(
_exceptionable,
{
method: "typia.json.assertParse",
path: _path + ".age",
expected: 'number & Type<"uint32">',
value: input.age,
},
_errorFactory,
)) &&
(19 < input.age ||
__typia_transform__assertGuard._assertGuard(
_exceptionable,
{
method: "typia.json.assertParse",
path: _path + ".age",
expected: "number & ExclusiveMinimum<19>",
value: input.age,
},
_errorFactory,
)) &&
(input.age <= 100 ||
__typia_transform__assertGuard._assertGuard(
_exceptionable,
{
method: "typia.json.assertParse",
path: _path + ".age",
expected: "number & Maximum<100>",
value: input.age,
},
_errorFactory,
))) ||
__typia_transform__assertGuard._assertGuard(
_exceptionable,
{
method: "typia.json.assertParse",
path: _path + ".age",
expected:
'(number & Type<"uint32"> & ExclusiveMinimum<19> & Maximum<100>)',
value: input.age,
},
_errorFactory,
));
const __is = (input) =>
"object" === typeof input && null !== input && _io0(input);
let _errorFactory;
const __assert = (input, errorFactory) => {
if (false === __is(input)) {
_errorFactory = errorFactory;
((input, _path, _exceptionable = true) =>
((("object" === typeof input && null !== input) ||
__typia_transform__assertGuard._assertGuard(
true,
{
method: "typia.json.assertParse",
path: _path + "",
expected: "IMember",
value: input,
},
_errorFactory,
)) &&
_ao0(input, _path + "", true)) ||
__typia_transform__assertGuard._assertGuard(
true,
{
method: "typia.json.assertParse",
path: _path + "",
expected: "IMember",
value: input,
},
_errorFactory,
))(input, "$input", true);
}
return input;
};
return (input, errorFactory) => __assert(JSON.parse(input), errorFactory);
})()(json);
console.log(json === JSON.stringify(parsed)); // true
Reusable functions
undefined
export namespace json {
export function createIsParse<T>(): (input: string) => Primitive<T> | null;
export function createAssertParse<T>(): (input: string) => Primitive<T>;
export function createValidateParse<T>(): (
input: string,
) => IValidation<Primitive<T>>;
}
undefined
/**
* Custom error class thrown when runtime assertion fails in `typia.assert<T>()` function.
*
* This error is thrown by the `typia.assert<T>()` function when the input value
* doesn't match the expected type.
*
* The error provides detailed information about the first assertion failure encountered,
* including the access path where the error occurred, the expected type, and the actual value.
*
* @template T - The expected type (generic for type safety)
* @author Jeongho Nam - https://github.com/samchon
* @example
* ```typescript
* interface IMember {
* name: string;
* age: number & ExclusiveMinimum<19>;
* }
*
* try {
* typia.assert<IMember>({ name: "John", age: 18 });
* } catch (error) {
* if (error instanceof TypeGuardError) {
* console.log(error.method); // "typia.assert"
* console.log(error.path); // "input.age"
* console.log(error.expected); // "number & ExclusiveMinimum<19>"
* console.log(error.value); // 18
* }
* }
* ```
*/
export class TypeGuardError<T = any> extends Error {
/**
* The name of the typia method that threw this error.
*
* @example "typia.assert"
*/
public readonly method: string;
/**
* The access path to the property where the assertion error occurred.
*
* Uses dot notation to indicate the path for nested object properties.
* May be `undefined` if the error occurred at the root level.
*
* @example
* - `"input.age"` - Error in the age property of the object
* - `"input.profile.email"` - Error in the email property of a nested object
* - `"input[0].name"` - Error in the name property of the first array element
* - `undefined` - Error occurred at the root level
*/
public readonly path: string | undefined;
/**
* String representation of the expected type at the error location.
*
* Represents TypeScript types as strings, including detailed type information
* for complex types.
*
* @example
* - `"string"` - Expected string type
* - `"number & ExclusiveMinimum<19>"` - Expected number greater than 19
* - `"undefined"` - Expected undefined (when superfluous property found in assertion)
* - `"{ name: string; age: number }"` - Expected object type
*/
public readonly expected: string;
/**
* The actual value that failed assertion.
*
* Stores the actual value at the error path as-is.
* Useful for debugging by comparing the expected type with the actual value.
*
* @example
* - `18` - Numeric value
* - `"invalid"` - String value
* - `{ name: "John", age: 18, sex: 1 }` - Object value
*/
public readonly value: any;
/**
* Phantom property for type safety purposes.
*
* This property is not actually used and exists only to maintain
* the generic type T in TypeScript's type system.
* Always has an `undefined` value at runtime.
*
* @internal
*/
protected readonly fake_expected_typed_value_?: T | undefined;
/**
* Creates a new TypeGuardError instance.
*
* @param props - Object containing the properties needed to create the error
*
* @example
* ```typescript
* const error = new TypeGuardError({
* method: "typia.assert",
* path: "input.age",
* expected: "number & ExclusiveMinimum<19>",
* value: 18
* });
* ```
*/
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.method = props.method;
this.path = props.path;
this.expected = props.expected;
this.value = props.value;
}
}
export namespace TypeGuardError {
/**
* Interface for properties passed to the TypeGuardError constructor.
*
* @example
* ```typescript
* const props: TypeGuardError.IProps = {
* method: "typia.assertEquals",
* path: "input.sex",
* expected: "undefined",
* value: 1,
* message: "Custom error message" // optional
* };
* ```
*/
export interface IProps {
/**
* The name of the typia method that threw the error.
*
* @example "typia.assert", "typia.assertEquals"
*/
method: string;
/**
* The access path to the property where the assertion error occurred (optional).
*
* @example "input.age", "input.profile.email"
*/
path?: undefined | string;
/**
* String representation of the expected type at the error location.
*
* @example "string", "number & ExclusiveMinimum<19>"
*/
expected: string;
/**
* The actual value that failed assertion.
*/
value: any;
/**
* Custom error message (optional).
*
* If not provided, a default format message will be automatically generated.
*/
message?: undefined | string;
}
}
undefined
/**
* Union type representing the result of type validation
*
* This is the return type of {@link typia.validate} functions, returning
* {@link IValidation.ISuccess} on validation success and
* {@link IValidation.IFailure} on validation failure. When validation fails, it
* provides detailed, granular error information that precisely describes what
* went wrong, where it went wrong, and what was expected.
*
* This comprehensive error reporting makes `IValidation` particularly valuable
* for AI function calling scenarios, where Large Language Models (LLMs) need
* specific feedback to correct their parameter generation. The detailed error
* information is used by ILlmFunction.validate() to provide validation feedback
* to AI agents, enabling iterative correction and improvement of function
* calling accuracy.
*
* This type uses the Discriminated Union pattern, allowing type specification
* through the success property:
*
* ```typescript
* const result = typia.validate<string>(input);
* if (result.success) {
* // IValidation.ISuccess<string> type
* console.log(result.data); // validated data accessible
* } else {
* // IValidation.IFailure type
* console.log(result.errors); // detailed error information accessible
* }
* ```
*
* @author Jeongho Nam - https://github.com/samchon
* @template T The type to validate
*/
export type IValidation<T = unknown> =
| IValidation.ISuccess<T>
| IValidation.IFailure;
export namespace IValidation {
/**
* Interface returned when type validation succeeds
*
* Returned when the input value perfectly conforms to the specified type T.
* Since success is true, TypeScript's type guard allows safe access to the
* validated data through the data property.
*
* @template T The validated type
*/
export interface ISuccess<T = unknown> {
/** Indicates validation success */
success: true;
/** The validated data of type T */
data: T;
}
/**
* Interface returned when type validation fails
*
* Returned when the input value does not conform to the expected type.
* Contains comprehensive error information designed to be easily understood
* by both humans and AI systems. Each error in the errors array provides
* precise details about validation failures, including the exact path to the
* problematic property, what type was expected, and what value was actually
* provided.
*
* This detailed error structure is specifically optimized for AI function
* calling validation feedback. When LLMs make type errors during function
* calling, these granular error reports enable the AI to understand exactly
* what went wrong and how to fix it, improving success rates in subsequent
* attempts.
*
* Example error scenarios:
*
* - Type mismatch: expected "string" but got number 5
* - Format violation: expected "string & Format<'uuid'>" but got
* "invalid-format"
* - Missing properties: expected "required property 'name'" but got undefined
* - Array type errors: expected "Array<string>" but got single string value
*
* The errors are used by ILlmFunction.validate() to provide structured
* feedback to AI agents, enabling them to correct their parameter generation
* and achieve improved function calling accuracy.
*/
export interface IFailure {
/** Indicates validation failure */
success: false;
/** The original input data that failed validation */
data: unknown;
/** Array of detailed validation errors */
errors: IError[];
}
/**
* Detailed information about a specific validation error
*
* Each error provides granular, actionable information about validation
* failures, designed to be immediately useful for both human developers and
* AI systems. The error structure follows a consistent format that enables
* precise identification and correction of type mismatches.
*
* This error format is particularly valuable for AI function calling
* scenarios, where LLMs need to understand exactly what went wrong to
* generate correct parameters. The combination of path, expected type, and
* actual value provides the AI with sufficient context to make accurate
* corrections, which is why ILlmFunction.validate() can achieve such high
* success rates in validation feedback loops.
*
* Real-world examples from AI function calling:
*
* {
* path: "input.member.age",
* expected: "number & Format<'uint32'>",
* value: 20.75 // AI provided float instead of uint32
* }
*
* {
* path: "input.categories",
* expected: "Array<string>",
* value: "technology" // AI provided string instead of array
* }
*
* {
* path: "input.id",
* expected: "string & Format<'uuid'>",
* value: "invalid-uuid-format" // AI provided malformed UUID
* }
*/
export interface IError {
/**
* The path to the property that failed validation (e.g.,
* "input.member.age")
*/
path: string;
/** Description of the expected type or format */
expected: string;
/** The actual value that caused the validation failure */
value: any;
}
}
undefined
import { Equal } from "./typings/Equal";
import { IsTuple } from "./typings/IsTuple";
import { NativeClass } from "./typings/NativeClass";
import { ValueOf } from "./typings/ValueOf";
import { Format } from "./tags";
/**
* Primitive type of JSON.
*
* `Primitive<T>` is a TMP (Type Meta Programming) type which converts
* its argument as a primitive type within framework JSON.
*
* If the target argument is a built-in class which returns its origin primitive type
* through the `valueOf()` method like the `String` or `Number`, its return type would
* be the `string` or `number`. Otherwise, the built-in class does not have the
* `valueOf()` method, the return type would be an empty object (`{}`).
*
* Otherwise, the target argument is a type of custom class, all of its custom method
* would be erased and its prototype would be changed to the primitive `object`.
* Therefore, return type of the TMP type finally be the primitive object.
*
* In addition, if the target argument is a type of custom class and it has a special
* method `toJSON()`, return type of this `Primitive` would be not `Primitive<Instance>`
* but `Primitive<ReturnType<Instance.toJSON>>`.
*
* Before | After
* ------------------------|----------------------------------------
* `Boolean` | `boolean`
* `Number` | `number`
* `String` | `string`
* `Class` | `object`
* `Class` with `toJSON()` | `Primitive<ReturnType<Class.toJSON>>`
* Native Class | never
* Others | No change
*
* @template T Target argument type.
* @author Jeongho Nam - https://github.com/samchon
* @author Kyungsu Kang - https://github.com/kakasoo
* @author Michael - https://github.com/8471919
*/
export type Primitive<T> =
Equal<T, PrimitiveMain<T>> extends true ? T : PrimitiveMain<T>;
type PrimitiveMain<Instance> = Instance extends [never]
? never // (special trick for jsonable | null) type
: ValueOf<Instance> extends bigint
? never
: ValueOf<Instance> extends boolean | number | string
? ValueOf<Instance>
: Instance extends Function
? never
: ValueOf<Instance> extends object
? Instance extends object
? Instance extends Date
? string & Format<"date-time">
: Instance extends IJsonable<infer Raw>
? ValueOf<Raw> extends object
? Raw extends object
? PrimitiveObject<Raw> // object would be primitified
: never // cannot be
: ValueOf<Raw> // atomic value
: Instance extends Exclude<NativeClass, Date>
? never
: PrimitiveObject<Instance> // object would be primitified
: never // cannot be
: ValueOf<Instance>;
type PrimitiveObject<Instance extends object> =
Instance extends Array<infer T>
? IsTuple<Instance> extends true
? PrimitiveTuple<Instance>
: PrimitiveMain<T>[]
: {
[P in keyof Instance]: PrimitiveMain<Instance[P]>;
};
type PrimitiveTuple<T extends readonly any[]> = T extends []
? []
: T extends [infer F]
? [PrimitiveMain<F>]
: T extends [infer F, ...infer Rest extends readonly any[]]
? [PrimitiveMain<F>, ...PrimitiveTuple<Rest>]
: T extends [(infer F)?]
? [PrimitiveMain<F>?]
: T extends [(infer F)?, ...infer Rest extends readonly any[]]
? [PrimitiveMain<F>?, ...PrimitiveTuple<Rest>]
: [];
interface IJsonable<T> {
toJSON(): T;
}
Reusable typia.json.isParse<T>()
function generators.
If you repeat to call typia.json.isParse<T>()
function on the same type, size of JavaScript files would be larger because of duplicated AOT compilation. To prevent it, you can generate reusable function through typia.createIsParse<T>()
function.
Just look at the code below, then you may understand how to use it.
TypeScript Source Code
import typia, { tags } from "typia";
export const parseMember = typia.json.createIsParse<IMember>();
interface IMember {
id: string & tags.Format<"uuid">;
email: string & tags.Format<"email">;
age: number &
tags.Type<"uint32"> &
tags.ExclusiveMinimum<19> &
tags.Maximum<100>;
}
Compiled JavaScript File
import typia from "typia";
import * as __typia_transform__isFormatEmail from "typia/lib/internal/_isFormatEmail.js";
import * as __typia_transform__isFormatUuid from "typia/lib/internal/_isFormatUuid.js";
import * as __typia_transform__isTypeUint32 from "typia/lib/internal/_isTypeUint32.js";
export const parseMember = (() => {
const _io0 = (input) =>
"string" === typeof input.id &&
__typia_transform__isFormatUuid._isFormatUuid(input.id) &&
"string" === typeof input.email &&
__typia_transform__isFormatEmail._isFormatEmail(input.email) &&
"number" === typeof input.age &&
__typia_transform__isTypeUint32._isTypeUint32(input.age) &&
19 < input.age &&
input.age <= 100;
const __is = (input) =>
"object" === typeof input && null !== input && _io0(input);
return (input) => {
input = JSON.parse(input);
return __is(input) ? input : null;
};
})();