application() function
undefined
export namespace llm {
// LLM FUNCTION CALLING APPLICATION SCHEMA
export function application<
App extends Record<string, any>,
Config extends Partial<ILlmSchema.IConfig> = {},
>(
config?: Partial<Pick<ILlmApplication.IConfig, "validate">>,
): ILlmApplication;
// STRUCTURED OUTPUT
export function parameters<
Parameters extends Record<string, any>,
Config extends Partial<ILlmSchema.IConfig> = {},
>(): ILlmSchema.IParameters;
// TYPE SCHEMA
export function schema<
T,
Config extends Partial<ILlmSchema.IConfig> = {},
>(
$defs: Record<string, ILlmSchema>,
): ILlmSchema;
}undefined
import { ILlmFunction } from "./ILlmFunction";
import { ILlmSchema } from "./ILlmSchema";
import { IValidation } from "./IValidation";
/**
* LLM function calling application.
*
* `ILlmApplication` is a collection of {@link ILlmFunction} schemas generated
* from a TypeScript class or interface by `typia.llm.application<App>()`. Each
* public method becomes an {@link ILlmFunction} that LLM agents can invoke.
*
* Configure behavior via {@link ILlmApplication.IConfig}:
*
* - {@link ILlmApplication.IConfig.validate}: Custom validation per method
* - {@link ILlmSchema.IConfig.strict}: OpenAI structured output mode
* - {@link ILlmSchema.IConfig.reference}: Control `$ref` inlining behavior
*
* @author Jeongho Nam - https://github.com/samchon
* @template Class Source class/interface type
*/
export interface ILlmApplication<Class extends object = any> {
/**
* Array of callable function schemas.
*
* Each function represents a method from the source class that the LLM can
* invoke. Functions include parameter schemas, descriptions, and validation
* logic for type-safe function calling.
*/
functions: ILlmFunction[];
/**
* Configuration used to generate this application.
*
* Contains the settings that were applied during schema generation, including
* reference handling, strict mode, and parameter separation.
*/
config: ILlmApplication.IConfig<Class>;
/**
* Phantom property for TypeScript generic type preservation.
*
* This property exists only in the type system to preserve the `Class`
* generic parameter at compile time. It is always `undefined` at runtime and
* should not be accessed or used in application code.
*
* This pattern enables type inference to recover the original class type from
* an `ILlmApplication` instance, useful for type-safe function routing.
*/
__class?: Class | undefined;
}
export namespace ILlmApplication {
/**
* Configuration for LLM application generation.
*
* Extends {@link ILlmSchema.IConfig} with application-specific options for
* custom validation. These settings control how the application schema is
* generated from the source class.
*/
export interface IConfig<Class extends object = any>
extends ILlmSchema.IConfig {
/**
* Custom validation functions per method name.
*
* Allows overriding the default type-based validation with custom business
* logic. Useful for complex validation rules that cannot be expressed in
* JSON Schema.
*
* @default null (use default type validation)
*/
validate: null | Partial<ILlmApplication.IValidationHook<Class>>;
}
/**
* Type-safe mapping of method names to custom validators.
*
* Maps each method name to a validation function that receives the raw input
* and returns a validation result. The type inference ensures validators
* match the expected argument types.
*
* @template Class - The source class type for type inference
*/
export type IValidationHook<Class extends object> = {
[K in keyof Class]?: Class[K] extends (args: infer Argument) => unknown
? (input: unknown) => IValidation<Argument>
: never;
};
/**
* Internal type for typia transformer.
*
* @ignore
*/
export interface __IPrimitive<Class extends object = any> extends Omit<
ILlmApplication<Class>,
"config" | "functions"
> {
functions: Omit<ILlmFunction, "parse">[];
}
}undefined
import { ILlmSchema } from "./ILlmSchema";
import { IValidation } from "./IValidation";
/**
* LLM function calling metadata.
*
* `ILlmFunction` describes a single callable function for LLM agents. Generated
* as part of {@link ILlmApplication} by `typia.llm.application<App>()`.
*
* Contains the function {@link name} (max 64 chars for OpenAI),
* {@link parameters} schema for input types, optional {@link output} schema for
* return type, and {@link description} for LLM to understand the function's
* purpose.
*
* The built-in {@link validate} function checks LLM-generated arguments against
* the schema, enabling auto-correction when the LLM makes type errors (e.g.,
* returning `"123"` instead of `123`).
*
* @author Jeongho Nam - https://github.com/samchon
*/
export interface ILlmFunction {
/**
* Function name for LLM invocation.
*
* The identifier used by the LLM to call this function. Must be unique within
* the application. OpenAI limits function names to 64 characters.
*
* @maxLength 64
*/
name: string;
/**
* Schema for function parameters.
*
* Defines the expected argument types as a JSON Schema object. Contains
* `$defs` for shared type definitions and `properties` for each named
* parameter.
*/
parameters: ILlmSchema.IParameters;
/**
* Schema for the return type.
*
* Defines the expected output type as an object parameters schema, wrapping
* the return type in an {@link ILlmSchema.IParameters} object with `$defs` for
* shared type definitions and `properties` for the structured output.
*
* `undefined` when the function returns `void` or has no meaningful return
* value.
*/
output?: ILlmSchema.IParameters | undefined;
/**
* Human-readable function description.
*
* Explains what the function does, when to use it, and any important
* considerations. This description is crucial for LLMs to understand when to
* invoke this function. Extracted from JSDoc comments.
*/
description?: string | undefined;
/**
* Whether this function is deprecated.
*
* When `true`, indicates the function should no longer be used. LLMs may
* still invoke deprecated functions but should prefer non-deprecated
* alternatives when available.
*/
deprecated?: boolean | undefined;
/**
* Category tags for function organization.
*
* Extracted from `@tag` JSDoc annotations. Useful for grouping related
* functions and filtering the function list.
*/
tags?: string[] | undefined;
/**
* Lenient JSON parser with schema-based coercion.
*
* Parses incomplete/malformed JSON (unclosed brackets, trailing commas,
* unclosed strings) and coerces double-stringified values using the
* function's own {@link parameters} schema.
*
* This does NOT perform type validation — use {@link validate} after
* parsing to check the result.
*
* @param str Raw JSON string from LLM output
* @returns Validation result with parsed data or syntax errors
*/
parse: (str: string) => IValidation<unknown>;
/**
* Validates LLM-generated arguments against the schema.
*
* LLMs frequently make type errors such as returning strings instead of
* numbers or missing required properties. Use this validator to check
* arguments before execution.
*
* When validation fails, use `stringifyValidationFailure()` from
* `@typia/utils` to format the error for LLM feedback. The formatted output
* shows the invalid JSON with inline error comments, helping the LLM
* understand and correct its mistakes in the next turn.
*
* @param args The arguments generated by the LLM
* @returns Validation result with success status and any errors
* @see stringifyValidationFailure Format errors for LLM auto-correction
*/
validate: (args: unknown) => IValidation<unknown>;
}undefined
import { tags } from "../index";
import { IJsonSchemaAttribute } from "./IJsonSchemaAttribute";
/**
* Type schema for LLM function calling.
*
* `ILlmSchema` is a JSON Schema subset designed for LLM function calling
* compatibility. Most LLMs (OpenAI GPT, Anthropic Claude, Google Gemini, etc.)
* do not fully support JSON Schema, so this simplified schema omits unsupported
* features like tuples, `const`, and mixed union types.
*
* Generated by `typia.llm.schema<T>()` for single types or included in
* {@link ILlmApplication} via `typia.llm.application<Class>()`. Shared type
* definitions use `$defs` with `$ref` references to reduce duplication and
* handle recursive structures.
*
* Set {@link ILlmSchema.IConfig.strict} to `true` for OpenAI's structured output
* mode, which requires all properties to be `required` and
* `additionalProperties: false`.
*
* @author Jeongho Nam - https://github.com/samchon
*/
export type ILlmSchema =
| ILlmSchema.IBoolean
| ILlmSchema.IInteger
| ILlmSchema.INumber
| ILlmSchema.IString
| ILlmSchema.IArray
| ILlmSchema.IObject
| ILlmSchema.IReference
| ILlmSchema.IAnyOf
| ILlmSchema.INull
| ILlmSchema.IUnknown;
export namespace ILlmSchema {
/**
* Configuration options for LLM schema generation.
*
* Controls how TypeScript types are converted to LLM-compatible JSON schemas.
* These settings affect reference handling and OpenAI structured output
* compatibility.
*/
export interface IConfig {
/**
* Whether to allow `$ref` references everywhere.
*
* When `false`, references are inlined except for recursive types.
* References reduce token cost but may cause hallucination.
*
* @default true
*/
reference: boolean;
/**
* Whether to enable strict mode (OpenAI structured output).
*
* When `true`, all properties become required and `additionalProperties` is
* forced to `false`.
*
* @default false
*/
strict: boolean;
}
/**
* Function parameters schema with shared type definitions.
*
* Extends the object schema to include a `$defs` map for named type
* definitions that can be referenced via `$ref`. This structure allows
* recursive types and reduces schema duplication.
*
* The `additionalProperties` is always `false` for parameters to ensure
* strict argument validation and prevent unexpected properties.
*/
export interface IParameters extends Omit<IObject, "additionalProperties"> {
/**
* Named schema definitions for reference.
*
* Contains type definitions that can be referenced throughout the schema
* using `$ref: "#/$defs/TypeName"`. Essential for recursive types and
* shared structures.
*/
$defs: Record<string, ILlmSchema>;
/**
* Whether additional properties are allowed.
*
* Always `false` for function parameters to ensure strict type checking.
* This prevents LLMs from hallucinating extra properties.
*/
additionalProperties: false;
}
/**
* Boolean type schema.
*
* Represents a JSON Schema boolean type with optional enum constraints and
* default value. Used for true/false parameters and flags.
*/
export interface IBoolean extends IJsonSchemaAttribute.IBoolean {
/**
* Allowed boolean values.
*
* Restricts the value to specific boolean literals. Typically unused since
* booleans only have two possible values, but supported for consistency
* with other types.
*/
enum?: Array<boolean>;
/**
* Default value when not provided.
*
* The boolean value to use when the LLM omits this parameter.
*/
default?: boolean;
}
/**
* Integer type schema.
*
* Represents a JSON Schema integer type with numeric constraints. Maps to
* TypeScript `number` with integer validation. Supports range constraints,
* enum restrictions, and divisibility checks.
*/
export interface IInteger extends IJsonSchemaAttribute.IInteger {
/**
* Allowed integer values.
*
* Restricts the value to specific integer literals. Useful for representing
* enum-like integer codes or limited value sets.
*/
enum?: Array<number & tags.Type<"int64">>;
/**
* Default value when not provided.
*
* The integer value to use when the LLM omits this parameter.
*/
default?: number & tags.Type<"int64">;
/**
* Minimum value (inclusive).
*
* The value must be greater than or equal to this number.
*/
minimum?: number & tags.Type<"int64">;
/**
* Maximum value (inclusive).
*
* The value must be less than or equal to this number.
*/
maximum?: number & tags.Type<"int64">;
/**
* Exclusive minimum value.
*
* The value must be strictly greater than this number.
*/
exclusiveMinimum?: number & tags.Type<"int64">;
/**
* Exclusive maximum value.
*
* The value must be strictly less than this number.
*/
exclusiveMaximum?: number & tags.Type<"int64">;
/**
* Value must be divisible by this number.
*
* Used for constraints like "must be even" (multipleOf: 2) or "must be a
* multiple of 100" (multipleOf: 100).
*/
multipleOf?: number & tags.Type<"uint64"> & tags.ExclusiveMinimum<0>;
}
/**
* Number (floating-point) type schema.
*
* Represents a JSON Schema number type for floating-point values. Maps to
* TypeScript `number` type. Supports range constraints, enum restrictions,
* and precision checks via multipleOf.
*/
export interface INumber extends IJsonSchemaAttribute.INumber {
/**
* Allowed numeric values.
*
* Restricts the value to specific number literals. Useful for representing
* specific valid values like percentages or rates.
*/
enum?: Array<number>;
/**
* Default value when not provided.
*
* The number to use when the LLM omits this parameter.
*/
default?: number;
/**
* Minimum value (inclusive).
*
* The value must be greater than or equal to this number.
*/
minimum?: number;
/**
* Maximum value (inclusive).
*
* The value must be less than or equal to this number.
*/
maximum?: number;
/**
* Exclusive minimum value.
*
* The value must be strictly greater than this number.
*/
exclusiveMinimum?: number;
/**
* Exclusive maximum value.
*
* The value must be strictly less than this number.
*/
exclusiveMaximum?: number;
/**
* Value must be divisible by this number.
*
* Useful for decimal precision constraints like "two decimal places"
* (multipleOf: 0.01) or currency amounts (multipleOf: 0.01).
*/
multipleOf?: number & tags.ExclusiveMinimum<0>;
}
/**
* String type schema.
*
* Represents a JSON Schema string type with format validation, pattern
* matching, and length constraints. Maps to TypeScript `string` type with
* optional semantic format annotations.
*/
export interface IString extends IJsonSchemaAttribute.IString {
/**
* Allowed string values.
*
* Restricts the value to specific string literals. Maps directly to
* TypeScript string literal union types.
*/
enum?: Array<string>;
/**
* Default value when not provided.
*
* The string to use when the LLM omits this parameter.
*/
default?: string;
/**
* Semantic format specifier.
*
* Indicates the string represents a specific format like email, UUID, or
* date-time. LLMs may use this to generate appropriate values. Common
* formats include "email", "uri", "uuid", "date-time".
*/
format?:
| "binary"
| "byte"
| "password"
| "regex"
| "uuid"
| "email"
| "hostname"
| "idn-email"
| "idn-hostname"
| "iri"
| "iri-reference"
| "ipv4"
| "ipv6"
| "uri"
| "uri-reference"
| "uri-template"
| "url"
| "date-time"
| "date"
| "time"
| "duration"
| "json-pointer"
| "relative-json-pointer"
| (string & {});
/**
* Regular expression pattern for validation.
*
* The string must match this regex pattern. Note that LLMs may struggle
* with complex regex patterns; simple patterns work best.
*/
pattern?: string;
/**
* MIME type of the string content.
*
* Indicates the content type when the string contains encoded binary data,
* such as "application/json" or "image/png".
*/
contentMediaType?: string;
/**
* Minimum string length.
*
* The string must have at least this many characters.
*/
minLength?: number & tags.Type<"uint64">;
/**
* Maximum string length.
*
* The string must have at most this many characters.
*/
maxLength?: number & tags.Type<"uint64">;
}
/**
* Array type schema.
*
* Represents a JSON Schema array type with item type validation and size
* constraints. Maps to TypeScript `T[]` or `Array<T>` types. Note: Tuple
* types are not supported by LLM schemas.
*/
export interface IArray extends IJsonSchemaAttribute.IArray {
/**
* Schema for array elements.
*
* All elements in the array must conform to this schema. For heterogeneous
* arrays, use an `anyOf` schema.
*/
items: ILlmSchema;
/**
* Whether elements must be unique.
*
* When `true`, no two elements may be equal. Maps to TypeScript `Set<T>`
* semantics but represented as an array.
*/
uniqueItems?: boolean;
/**
* Minimum number of elements.
*
* The array must contain at least this many items.
*/
minItems?: number & tags.Type<"uint64">;
/**
* Maximum number of elements.
*
* The array must contain at most this many items.
*/
maxItems?: number & tags.Type<"uint64">;
}
/**
* Object type schema.
*
* Represents a JSON Schema object type with named properties. Maps to
* TypeScript interface or object type. Supports required property
* declarations and dynamic additional properties.
*/
export interface IObject extends IJsonSchemaAttribute.IObject {
/**
* Property name to schema mapping.
*
* Defines the type of each named property on the object. All properties are
* defined here regardless of whether they are required or optional.
*/
properties: Record<string, ILlmSchema>;
/**
* Schema for dynamic/additional properties.
*
* - `false` (default): No additional properties allowed
* - `true`: Any additional properties allowed
* - Schema: Additional properties must match this schema
*
* Note: ChatGPT and Gemini do not support `additionalProperties`. Use
* {@link ILlmSchema.IConfig.strict} mode for OpenAI compatibility.
*/
additionalProperties?: ILlmSchema | boolean;
/**
* List of required property names.
*
* Properties in this array must be present in the object. In strict mode,
* all properties become required automatically.
*/
required: string[];
}
/**
* Reference to a named schema definition.
*
* Points to a schema defined in the `$defs` map using a JSON pointer. Used to
* avoid schema duplication and enable recursive type definitions. The
* reference path format is `#/$defs/TypeName`.
*/
export interface IReference extends IJsonSchemaAttribute {
/**
* JSON pointer to the referenced schema.
*
* Must be in the format `#/$defs/TypeName` where TypeName is a key in the
* parent schema's `$defs` map.
*/
$ref: string;
}
/**
* Union type schema (A | B | C).
*
* Represents a TypeScript union type where the value can match any one of the
* member schemas. Note: Gemini does not support `anyOf`/`oneOf` schemas. Use
* discriminated unions with `x-discriminator` when possible for better LLM
* comprehension.
*/
export interface IAnyOf extends IJsonSchemaAttribute {
/**
* Array of possible schemas.
*
* The value must match at least one of these schemas. Nested `anyOf`
* schemas are flattened to avoid deep nesting.
*/
anyOf: Exclude<ILlmSchema, ILlmSchema.IAnyOf>[];
/**
* Discriminator for tagged/discriminated unions.
*
* Helps LLMs understand which variant to select based on a discriminating
* property value. Improves type inference accuracy.
*/
"x-discriminator"?: IAnyOf.IDiscriminator;
}
export namespace IAnyOf {
/**
* Discriminator configuration for tagged unions.
*
* Specifies which property distinguishes between union variants and maps
* discriminator values to their corresponding schemas.
*/
export interface IDiscriminator {
/**
* Name of the discriminating property.
*
* This property must exist on all union member object schemas and contain
* unique literal values that identify each variant.
*/
propertyName: string;
/**
* Mapping from discriminator values to schema references.
*
* Keys are the literal values of the discriminator property, values are
* `$ref` paths to the corresponding schemas.
*/
mapping?: Record<string, string>;
}
}
/**
* Null type schema.
*
* Represents the JSON null value. In TypeScript union types like `T | null`,
* this schema appears in an `anyOf` alongside the T schema.
*/
export interface INull extends IJsonSchemaAttribute.INull {}
/**
* Unknown/any type schema.
*
* Represents TypeScript `any` or `unknown` types where no specific type
* constraint is defined. Use sparingly as LLMs may generate unexpected values
* for unconstrained types.
*/
export interface IUnknown extends IJsonSchemaAttribute.IUnknown {}
}LLM function calling application schema from a native TypeScript class or interface type.
typia.llm.application<App>() is a function composing LLM (Large Language Model) calling application schema from a native TypeScript class or interface type. The function returns an ILlmApplication instance, which is a data structure representing a collection of LLM function calling schemas.
If you put LLM function schema instances registered in the ILlmApplication.functions to the LLM provider like OpenAI ChatGPT, the LLM will select a proper function to call with parameter values of the target function in the conversations with the user. This is the “LLM Function Calling”.
Let’s make A.I. Chatbot super-easily with typia.llm.application<App>() function.
LLM Function Calling and Structured Output
LLM selects proper function and fill arguments.
In nowadays, most LLM (Large Language Model) like OpenAI are supporting “function calling” feature. The “LLM function calling” means that LLM automatically selects a proper function and fills parameter values from conversation with the user (may by chatting text).
Structured output is another feature of LLM. The “structured output” means that LLM automatically transforms the output conversation into a structured data format like JSON.
TypeScript Source Code
import typia, { ILlmApplication } from "typia";
import { BbsArticleService } from "./BbsArticleService";
const app: ILlmApplication = typia.llm.application<BbsArticleService>();
console.log(app);Compiled JavaScript
import typia from "typia";
import * as __typia_transform__isFormatUri from "typia/lib/internal/_isFormatUri";
import * as __typia_transform__isFormatUuid from "typia/lib/internal/_isFormatUuid";
import * as __typia_transform__llmApplicationFinalize from "typia/lib/internal/_llmApplicationFinalize";
import * as __typia_transform__validateReport from "typia/lib/internal/_validateReport";
const app = __typia_transform__llmApplicationFinalize._llmApplicationFinalize({
functions: [
{
name: "index",
parameters: {
type: "object",
properties: {},
additionalProperties: false,
required: [],
$defs: {},
},
output: {
description:
"Page of articles.\n\n------------------------------\n\nDescription of the current {@link IBbsArticle.IPage} type:\n\n> Page of articles.\n\n------------------------------\n\nDescription of the parent {@link IBbsArticle} type:\n\n> Article entity.\n> \n> `IBbsArticle` is an entity representing an article in the BBS (Bulletin Board\n> System).",
type: "object",
properties: {
articles: {
description: "List of articles.",
type: "array",
items: {
$ref: "#/$defs/IBbsArticle",
},
},
},
required: ["articles"],
additionalProperties: false,
$defs: {
IBbsArticle: {
description:
"Article entity.\n\n`IBbsArticle` is an entity representing an article in the BBS (Bulletin Board\nSystem).",
type: "object",
properties: {
id: {
description: "Primary Key.",
type: "string",
format: "uuid",
},
created_at: {
description: "Creation time of the article.",
type: "string",
format: "date-time",
},
updated_at: {
description: "Last updated time of the article.",
type: "string",
format: "date-time",
},
title: {
description:
"Title of the article.\n\nRepresentative title of the article.",
type: "string",
},
body: {
description:
"Content body.\n\nContent body of the article written in the markdown format.",
type: "string",
},
thumbnail: {
description:
"Thumbnail image URI.\n\nThumbnail image URI which can represent the article.\n\nIf configured as `null`, it means that no thumbnail image in the article.",
anyOf: [
{
type: "null",
},
{
type: "string",
format: "uri",
contentMediaType: "image/*",
},
],
},
},
required: [
"id",
"created_at",
"updated_at",
"title",
"body",
"thumbnail",
],
},
},
},
description:
"Get all articles.\n\nList up every articles archived in the BBS DB.",
validate: (() => {
const __is = (input) => true;
let errors;
let _report;
return (input) => {
if (false === __is(input)) {
errors = [];
_report = __typia_transform__validateReport._validateReport(errors);
((input, _path, _exceptionable = true) => true)(
input,
"$input",
true,
);
const success = 0 === errors.length;
return success
? {
success,
data: input,
}
: {
success,
errors,
data: input,
};
}
return {
success: true,
data: input,
};
};
})(),
},
{
name: "create",
parameters: {
description: " Properties of create function",
type: "object",
properties: {
input: {
description: "Information of the article to create",
$ref: "#/$defs/IBbsArticle.ICreate",
},
},
required: ["input"],
additionalProperties: false,
$defs: {
"IBbsArticle.ICreate": {
description: "Information of the article to create.",
type: "object",
properties: {
title: {
description:
"Title of the article.\n\nRepresentative title of the article.",
type: "string",
},
body: {
description:
"Content body.\n\nContent body of the article written in the markdown format.",
type: "string",
},
thumbnail: {
description:
"Thumbnail image URI.\n\nThumbnail image URI which can represent the article.\n\nIf configured as `null`, it means that no thumbnail image in the article.",
anyOf: [
{
type: "null",
},
{
type: "string",
format: "uri",
contentMediaType: "image/*",
},
],
},
},
required: ["title", "body", "thumbnail"],
},
},
},
output: {
description:
"Article entity.\n\n`IBbsArticle` is an entity representing an article in the BBS (Bulletin Board\nSystem).\n\n------------------------------\n\nDescription of the current {@link IBbsArticle} type:\n\n> Article entity.\n> \n> `IBbsArticle` is an entity representing an article in the BBS (Bulletin Board\n> System).",
type: "object",
properties: {
id: {
description: "Primary Key.",
type: "string",
format: "uuid",
},
created_at: {
description: "Creation time of the article.",
type: "string",
format: "date-time",
},
updated_at: {
description: "Last updated time of the article.",
type: "string",
format: "date-time",
},
title: {
description:
"Title of the article.\n\nRepresentative title of the article.",
type: "string",
},
body: {
description:
"Content body.\n\nContent body of the article written in the markdown format.",
type: "string",
},
thumbnail: {
description:
"Thumbnail image URI.\n\nThumbnail image URI which can represent the article.\n\nIf configured as `null`, it means that no thumbnail image in the article.",
anyOf: [
{
type: "null",
},
{
type: "string",
format: "uri",
contentMediaType: "image/*",
},
],
},
},
required: [
"id",
"created_at",
"updated_at",
"title",
"body",
"thumbnail",
],
additionalProperties: false,
$defs: {},
},
description:
"Create a new article.\n\nWrites a new article and archives it into the DB.",
validate: (() => {
const _io0 = (input) =>
"object" === typeof input.input &&
null !== input.input &&
_io1(input.input);
const _io1 = (input) =>
"string" === typeof input.title &&
"string" === typeof input.body &&
(null === input.thumbnail ||
("string" === typeof input.thumbnail &&
__typia_transform__isFormatUri._isFormatUri(input.thumbnail)));
const _vo0 = (input, _path, _exceptionable = true) =>
[
((("object" === typeof input.input && null !== input.input) ||
_report(_exceptionable, {
path: _path + ".input",
expected: "IBbsArticle.ICreate",
value: input.input,
})) &&
_vo1(input.input, _path + ".input", true && _exceptionable)) ||
_report(_exceptionable, {
path: _path + ".input",
expected: "IBbsArticle.ICreate",
value: input.input,
}),
].every((flag) => flag);
const _vo1 = (input, _path, _exceptionable = true) =>
[
"string" === typeof input.title ||
_report(_exceptionable, {
path: _path + ".title",
expected: "string",
value: input.title,
}),
"string" === typeof input.body ||
_report(_exceptionable, {
path: _path + ".body",
expected: "string",
value: input.body,
}),
null === input.thumbnail ||
("string" === typeof input.thumbnail &&
(__typia_transform__isFormatUri._isFormatUri(input.thumbnail) ||
_report(_exceptionable, {
path: _path + ".thumbnail",
expected: 'string & Format<"uri">',
value: input.thumbnail,
}))) ||
_report(_exceptionable, {
path: _path + ".thumbnail",
expected:
'((string & Format<"uri"> & ContentMediaType<"image/*">) | null)',
value: input.thumbnail,
}),
].every((flag) => flag);
const __is = (input) =>
"object" === typeof input && null !== input && _io0(input);
let errors;
let _report;
return (input) => {
if (false === __is(input)) {
errors = [];
_report = __typia_transform__validateReport._validateReport(errors);
((input, _path, _exceptionable = true) =>
((("object" === typeof input && null !== input) ||
_report(true, {
path: _path + "",
expected: "__type",
value: input,
})) &&
_vo0(input, _path + "", true)) ||
_report(true, {
path: _path + "",
expected: "__type",
value: input,
}))(input, "$input", true);
const success = 0 === errors.length;
return success
? {
success,
data: input,
}
: {
success,
errors,
data: input,
};
}
return {
success: true,
data: input,
};
};
})(),
},
{
name: "update",
parameters: {
description: " Properties of update function",
type: "object",
properties: {
id: {
description: "Target article's {@link IBbsArticle.id}.",
type: "string",
format: "uuid",
},
input: {
description: "New content to update.",
$ref: "#/$defs/PartialIBbsArticle.ICreate",
},
},
required: ["id", "input"],
additionalProperties: false,
$defs: {
"PartialIBbsArticle.ICreate": {
description: "Make all properties in T optional",
type: "object",
properties: {
title: {
description:
"Title of the article.\n\nRepresentative title of the article.",
type: "string",
},
body: {
description:
"Content body.\n\nContent body of the article written in the markdown format.",
type: "string",
},
thumbnail: {
description:
"Thumbnail image URI.\n\nThumbnail image URI which can represent the article.\n\nIf configured as `null`, it means that no thumbnail image in the article.",
anyOf: [
{
type: "null",
},
{
type: "string",
format: "uri",
contentMediaType: "image/*",
},
],
},
},
required: [],
},
},
},
description: "Update an article.\n\nUpdates an article with new content.",
validate: (() => {
const _io0 = (input) =>
"string" === typeof input.id &&
__typia_transform__isFormatUuid._isFormatUuid(input.id) &&
"object" === typeof input.input &&
null !== input.input &&
false === Array.isArray(input.input) &&
_io1(input.input);
const _io1 = (input) =>
(undefined === input.title || "string" === typeof input.title) &&
(undefined === input.body || "string" === typeof input.body) &&
(null === input.thumbnail ||
undefined === input.thumbnail ||
("string" === typeof input.thumbnail &&
__typia_transform__isFormatUri._isFormatUri(input.thumbnail)));
const _vo0 = (input, _path, _exceptionable = true) =>
[
("string" === typeof input.id &&
(__typia_transform__isFormatUuid._isFormatUuid(input.id) ||
_report(_exceptionable, {
path: _path + ".id",
expected: 'string & Format<"uuid">',
value: input.id,
}))) ||
_report(_exceptionable, {
path: _path + ".id",
expected: '(string & Format<"uuid">)',
value: input.id,
}),
((("object" === typeof input.input &&
null !== input.input &&
false === Array.isArray(input.input)) ||
_report(_exceptionable, {
path: _path + ".input",
expected: "Partial<IBbsArticle.ICreate>",
value: input.input,
})) &&
_vo1(input.input, _path + ".input", true && _exceptionable)) ||
_report(_exceptionable, {
path: _path + ".input",
expected: "Partial<IBbsArticle.ICreate>",
value: input.input,
}),
].every((flag) => flag);
const _vo1 = (input, _path, _exceptionable = true) =>
[
undefined === input.title ||
"string" === typeof input.title ||
_report(_exceptionable, {
path: _path + ".title",
expected: "(string | undefined)",
value: input.title,
}),
undefined === input.body ||
"string" === typeof input.body ||
_report(_exceptionable, {
path: _path + ".body",
expected: "(string | undefined)",
value: input.body,
}),
null === input.thumbnail ||
undefined === input.thumbnail ||
("string" === typeof input.thumbnail &&
(__typia_transform__isFormatUri._isFormatUri(input.thumbnail) ||
_report(_exceptionable, {
path: _path + ".thumbnail",
expected: 'string & Format<"uri">',
value: input.thumbnail,
}))) ||
_report(_exceptionable, {
path: _path + ".thumbnail",
expected:
'((string & Format<"uri"> & ContentMediaType<"image/*">) | null | undefined)',
value: input.thumbnail,
}),
].every((flag) => flag);
const __is = (input) =>
"object" === typeof input && null !== input && _io0(input);
let errors;
let _report;
return (input) => {
if (false === __is(input)) {
errors = [];
_report = __typia_transform__validateReport._validateReport(errors);
((input, _path, _exceptionable = true) =>
((("object" === typeof input && null !== input) ||
_report(true, {
path: _path + "",
expected: "__type",
value: input,
})) &&
_vo0(input, _path + "", true)) ||
_report(true, {
path: _path + "",
expected: "__type",
value: input,
}))(input, "$input", true);
const success = 0 === errors.length;
return success
? {
success,
data: input,
}
: {
success,
errors,
data: input,
};
}
return {
success: true,
data: input,
};
};
})(),
},
{
name: "erase",
parameters: {
description: " Properties of erase function",
type: "object",
properties: {
id: {
description: "Target article's {@link IBbsArticle.id}.",
type: "string",
format: "uuid",
},
},
required: ["id"],
additionalProperties: false,
$defs: {},
},
description: "Erase an article.\n\nErases an article from the DB.",
validate: (() => {
const _io0 = (input) =>
"string" === typeof input.id &&
__typia_transform__isFormatUuid._isFormatUuid(input.id);
const _vo0 = (input, _path, _exceptionable = true) =>
[
("string" === typeof input.id &&
(__typia_transform__isFormatUuid._isFormatUuid(input.id) ||
_report(_exceptionable, {
path: _path + ".id",
expected: 'string & Format<"uuid">',
value: input.id,
}))) ||
_report(_exceptionable, {
path: _path + ".id",
expected: '(string & Format<"uuid">)',
value: input.id,
}),
].every((flag) => flag);
const __is = (input) =>
"object" === typeof input && null !== input && _io0(input);
let errors;
let _report;
return (input) => {
if (false === __is(input)) {
errors = [];
_report = __typia_transform__validateReport._validateReport(errors);
((input, _path, _exceptionable = true) =>
((("object" === typeof input && null !== input) ||
_report(true, {
path: _path + "",
expected: "__type",
value: input,
})) &&
_vo0(input, _path + "", true)) ||
_report(true, {
path: _path + "",
expected: "__type",
value: input,
}))(input, "$input", true);
const success = 0 === errors.length;
return success
? {
success,
data: input,
}
: {
success,
errors,
data: input,
};
}
return {
success: true,
data: input,
};
};
})(),
},
],
});
console.log(app);undefined
import { tags } from "typia";
import { IBbsArticle } from "./IBbsArticle";
export declare class BbsArticleService {
/**
* Get all articles.
*
* List up every articles archived in the BBS DB.
*
* @returns List of every articles
*/
public index(): IBbsArticle.IPage;
/**
* Create a new article.
*
* Writes a new article and archives it into the DB.
*
* @param props Properties of create function
* @returns Newly created article
*/
public create(props: {
/** Information of the article to create */
input: IBbsArticle.ICreate;
}): IBbsArticle;
/**
* Update an article.
*
* Updates an article with new content.
*
* @param props Properties of update function
* @param input New content to update
*/
public update(props: {
/** Target article's {@link IBbsArticle.id}. */
id: string & tags.Format<"uuid">;
/** New content to update. */
input: IBbsArticle.IUpdate;
}): void;
/**
* Erase an article.
*
* Erases an article from the DB.
*
* @param props Properties of erase function
*/
public erase(props: {
/** Target article's {@link IBbsArticle.id}. */
id: string & tags.Format<"uuid">;
}): void;
}undefined
import { tags } from "typia";
/**
* Article entity.
*
* `IBbsArticle` is an entity representing an article in the BBS (Bulletin Board
* System).
*/
export interface IBbsArticle extends IBbsArticle.ICreate {
/** Primary Key. */
id: string & tags.Format<"uuid">;
/** Creation time of the article. */
created_at: string & tags.Format<"date-time">;
/** Last updated time of the article. */
updated_at: string & tags.Format<"date-time">;
}
export namespace IBbsArticle {
/** Information of the article to create. */
export interface ICreate {
/**
* Title of the article.
*
* Representative title of the article.
*/
title: string;
/**
* Content body.
*
* Content body of the article written in the markdown format.
*/
body: string;
/**
* Thumbnail image URI.
*
* Thumbnail image URI which can represent the article.
*
* If configured as `null`, it means that no thumbnail image in the article.
*/
thumbnail:
| null
| (string & tags.Format<"uri"> & tags.ContentMediaType<"image/*">);
}
/**
* Information of the article to update.
*
* Only the filled properties will be updated.
*/
export type IUpdate = Partial<ICreate>;
/** Page of articles. */
export interface IPage {
/** List of articles. */
articles: IBbsArticle[];
}
}Validation Feedback
typia.llm.application<App>() embeds typia.validate<T>() in every function for automatic argument validation. When validation fails, the error is returned as text content with inline // ❌ comments at each invalid property:
{
"name": "John",
"age": "twenty", // ❌ [{"path":"$input.age","expected":"number"}]
"email": "not-an-email", // ❌ [{"path":"$input.email","expected":"string & Format<\"email\">"}]
"hobbies": "reading" // ❌ [{"path":"$input.hobbies","expected":"Array<string>"}]
}The LLM reads this feedback and self-corrects on the next turn.
In the AutoBe project (AI-powered backend code generator), qwen3-coder-next showed only 6.75% raw function calling success rate on compiler AST types. However, with validation feedback, it reached 100%.
Working on compiler AST means working on any type and any use case.
// Compiler AST may be the hardest type structure possible
//
// Unlimited union types + unlimited depth + recursive references
export type IExpression =
| IBooleanLiteral
| INumericLiteral
| IStringLiteral
| IArrayLiteralExpression // <- recursive (contains IExpression[])
| IObjectLiteralExpression // <- recursive (contains IExpression)
| INullLiteral
| IUndefinedKeyword
| IIdentifier
| IPropertyAccessExpression // <- recursive
| IElementAccessExpression // <- recursive
| ITypeOfExpression // <- recursive
| IPrefixUnaryExpression // <- recursive
| IPostfixUnaryExpression // <- recursive
| IBinaryExpression // <- recursive (left & right)
| IArrowFunction // <- recursive (body is IExpression)
| ICallExpression // <- recursive (args are IExpression[])
| INewExpression // <- recursive
| IConditionalPredicate // <- recursive (then & else branches)
| ... // 30+ expression types totalRestrictions
typia.llm.application<App>() follows the same restrictions of below.
About the function parameters type, it follows the restriction of both typia.llm.parameters<Params>() and typia.llm.schema<T>() functions. Therefore, the parameters must be a keyworded object type with static keys without any dynamic keys. Also, the object type must not be nullable or optional.
About the return value type, it also follows the restriction of typia.llm.parameters<Params>() function. Therefore, the return type must be a keyworded object type with static keys, or void. Primitive types (like number, string, boolean), array types, and union types with undefined are not allowed as return types. If you need to return a primitive or array value, wrap it in an object type (e.g., { value: number } or { items: T[] }).
TypeScript Source Code
import typia, { ILlmApplication, tags } from "typia";
const app: ILlmApplication = typia.llm.application<BbsArticleController>();
console.log(app);
interface BbsArticleController {
/**
* Create a new article.
*
* Writes a new article and archives it into the DB.
*
* @param props Properties of create function
* @returns Newly created article
*/
create(props: {
/**
* Information of the article to create
*/
input: IBbsArticle.ICreate;
}): Promise<IBbsArticle | undefined>;
/**
* Add two numbers.
*
* @param props Properties of add function
* @returns The sum value
*/
add(props: { x: number; y: number }): number;
erase(id: string & tags.Format<"uuid">): Promise<void>;
}Console Output
src/examples/llm.application.violation.ts:4:29 - error TS(typia.llm.application): unsupported type detected
- BbsArticleController.create: unknown
- LLM application's function ("create")'s return type must not be union type with undefined.
- BbsArticleController.add: unknown
- LLM application's function ("add")'s return type must be an object type.
- BbsArticleController.erase: unknown
- LLM application's function ("erase")'s parameter must be an object type.
4 const app: ILlmApplication = typia.llm.application<BbsArticleController>();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Found 1 error in src/examples/llm.application.violation.ts:4