structuredOutput() function
undefined
export namespace llm {
// STRUCTURED OUTPUT
export function structuredOutput<
T extends Record<string, any>,
Config extends Partial<ILlmSchema.IConfig & { equals: boolean }> = {},
>(): ILlmStructuredOutput<T>;
// SCHEMA ONLY (use structuredOutput() for full interface)
export function parameters<
Parameters extends Record<string, any>,
Config extends Partial<ILlmSchema.IConfig> = {},
>(): ILlmSchema.IParameters;
}All-in-one interface for LLM structured output.
typia.llm.structuredOutput<T>() is a function generating ILlmStructuredOutput<T> containing everything needed for handling LLM structured outputs: the JSON schema for prompting, and functions for parsing, coercing, and validating responses.
parameters: JSON schema to pass to LLM providersparse: Lenient JSON parser with type coercioncoerce: Type coercion for pre-parsed objectsvalidate: Schema validation with error details
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.
When to use structuredOutput() vs parameters()
- Use
structuredOutput()when you need parsing, coercion, and validation together - Use
parameters()when you only need the schema (e.g., passing toresponse_format)
structuredOutput() is essentially parameters() + parse() + coerce() + validate() bundled together.
TypeScript Source Code
import { LlmJson } from "@typia/utils";
import OpenAI from "openai";
import typia, { tags } from "typia";
interface IMember {
email: string & tags.Format<"email">;
name: string;
age: number & tags.Minimum<0>;
hobbies: string[];
joined_at: string & tags.Format<"date">;
}
const main = async (): Promise<void> => {
// Generate structured output interface
const output = typia.llm.structuredOutput<IMember>();
// Use schema with OpenAI
const client: OpenAI = new OpenAI({
apiKey: "<YOUR_OPENAI_API_KEY>",
});
const completion: OpenAI.ChatCompletion =
await client.chat.completions.create({
model: "gpt-4o",
messages: [
{
role: "user",
content: [
"I am a new member of the community.",
"",
"My name is John Doe, and I am 25 years old.",
"I like playing basketball and reading books,",
"and joined to this community at 2022-01-01.",
].join("\n"),
},
],
response_format: {
type: "json_schema",
json_schema: {
name: "member",
schema: output.parameters as any,
},
},
});
// Parse LLM response with type coercion
const parsed = output.parse(completion.choices[0].message.content!);
if (!parsed.success) {
console.error("Parse failed:", parsed.errors);
return;
}
// Validate the parsed data
const validated = output.validate(parsed.data);
if (!validated.success) {
// Format errors for LLM feedback
console.error(LlmJson.stringify(validated));
return;
}
console.log("Success:", validated.data);
};
main().catch(console.error);Parse & Coerce
Parsing Example
const output = typia.llm.structuredOutput<IMember>();
// LLM returns raw JSON string
const jsonString = '{"name": "John", "age": "25"}';
// parse() handles lenient JSON + type coercion
const result = output.parse(jsonString);
if (result.success) {
console.log(result.data.age); // 25 (number, not string)
}Type Coercion:
LLMs frequently return wrong types. Both parse() and coerce() automatically fix these based on the schema:
"42"→42(when schema expects number)"true"→true(when schema expects boolean)"null"→null(when schema expects null)"{...}"→{...}(double-stringified objects)"[...]"→[...](double-stringified arrays)
0% → 100% Success Rate on Union Types
Qwen3.5 model shows 0% success rate when handling union types with double-stringified JSON objects. With type coercion, the success rate jumps to 100%.
For Pre-parsed Objects, Use coerce()
Some LLM SDKs (Anthropic, Vercel AI, LangChain, MCP) parse JSON internally and return JavaScript objects directly. In these cases, use coerce() instead of parse() to fix types without re-parsing.
For more details, see JSON Utilities.
Validation Feedback
import { LlmJson } from "@typia/utils";
const output = typia.llm.structuredOutput<IMember>();
const parsed = output.parse(llmResponse);
if (parsed.success) {
const validated = output.validate(parsed.data);
if (!validated.success) {
// Format errors for LLM to understand and self-correct
const feedback = LlmJson.stringify(validated);
console.log(feedback);
// Send feedback back to LLM for retry
}
}Formatted Error Output:
{
"name": "John",
"age": -5, // ❌ [{"path":"$input.age","expected":"number & Minimum<0>"}]
"email": "invalid", // ❌ [{"path":"$input.email","expected":"string & Format<\"email\">"}]
}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%.
Config Options
// Use validateEquals (strict mode - reject extra properties)
const strictOutput = typia.llm.structuredOutput<
IMember,
{ equals: true }
>();
// Strict validation rejects objects with extra properties
const result = strictOutput.validate({
name: "John",
age: 25,
email: "john@example.com",
hobbies: ["reading"],
extraField: "not allowed", // ❌ rejected
});Comparison
| Feature | parameters() | structuredOutput() |
|---|---|---|
| Schema generation | ✅ | ✅ |
parse() function | ❌ | ✅ |
coerce() function | ❌ | ✅ |
validate() function | ❌ | ✅ |
| Use case | Schema only | Full workflow |
For schema-only needs, use parameters(). For the complete structured output workflow, use structuredOutput().
Restrictions
typia.llm.structuredOutput<T>() follows the same restrictions as typia.llm.parameters<T>() and typia.llm.schema<T>() functions.
The type T must be a keyworded object type with static keys without any dynamic keys. Also, the object type must not be nullable or optional.
If you don’t follow the LLM’s keyworded arguments rule, typia.llm.structuredOutput<T>() will throw a compilation error.
TypeScript Source Code
import typia from "typia";
typia.llm.structuredOutput<string>();
typia.llm.structuredOutput<Record<string, boolean>>();
typia.llm.structuredOutput<Array<number>>();