cd /news/ai-tools/show-hn-jev-schema-builder-from-type… · home › topics › ai-tools › article
[ARTICLE · art-146236] src=typia.io ↗ pub= topic=ai-tools verified=true sentiment=· neutral

Show HN: Jev schema builder from TypeScript Type with Typia

Typia released a schema builder that generates Jev question schemas from TypeScript types, using property and enum comments to supply instructions and choice descriptions. The tool exposes typia.llm.evaluation<ITicketTriage>() to build a question map and answer decoder at compile time, and can be called directly via @typesafe-ai/sdk, through Vercel AI SDK's TypeSafe provider with experimental_decide(), or used with OpenAI Structured Outputs. The Jev examples target model jev-1.13.0 and require TYPESAFE_API_KEY for the direct SDK or TYPESAFE_AI_API_KEY for the Vercel AI SDK provider.

read4 min views1 publishedOct 6, 2026
Show HN: Jev schema builder from TypeScript Type with Typia
Image: source

TL;DR #

Generate Jev question schemas from TypeScript types. Property and enum comments supply the instructions and choice descriptions. Call Jev directly or through Vercel AI SDK. Decode the answers back into the declared TypeScript type. Use the same type with OpenAI. Generate JSON Schema for Structured Outputs and call the official openai SDK.

import typia, { tags } from "typia";
 
enum Department {
  /**
   * Payments, invoicing, refunds.
   *
   * Duplicate charges, failed cards, and plan changes belong here, even when
   * the customer also mentions a bug.
   *
   * @probability 0.3
   */
  billing = "billing",
 
  /**
   * Bugs, outages, and broken integrations.
   *
   * Paging an engineer is expensive, so only pick this when the customer
   * describes the product misbehaving.
   *
   * @probability 0.5
   */
  technical = "technical",
 
  /**
   * Pricing, upgrades, and new accounts.
   *
   * @probability 0.2
   */
  sales = "sales",
}
 
interface ITicketTriage {
  /**
   * Does the customer convey urgency?
   *
   * A deadline, an outage, lost revenue, or a threat to leave counts. An
   * impatient tone alone does not.
   */
  urgent: boolean;
 
  /**
   * Which team should handle this ticket?
   *
   * Decide by what the customer needs done, not by the words they use.
   */
  department: Department;
 
  /**
   * Does the customer ask for their money back?
   *
   * Complaining about a charge is not a request. The customer has to ask.
   */
  refund: boolean & tags.Probability<0.8>;
}
 
const triage = typia.llm.evaluation<ITicketTriage>();
const ticket = "I was charged twice this morning. Refund it now, or I leave.";

typia.llm.evaluation<ITicketTriage>() generates a question map and answer decoder at compile time. Boolean properties become yes/no questions; Department becomes a choice question. Property comments supply instructions, and enum member comments describe each option.

The Jev examples below send triage.questions with the same ticket. Jev performs the inference; triage.decode() checks its answers and returns the reconstructed ITicketTriage in result.data, or validation errors in result.errors.

import { TypeSafeClient } from "@typesafe-ai/sdk";
import { toJevQuestions } from "@typia/jev";
 
const client = new TypeSafeClient(); // reads TYPESAFE_API_KEY
const { answers } = await client.systemOne({
  model: "jev-1.13.0",
  state: ticket,
  questions: toJevQuestions(triage.questions),
});
 
const result = triage.decode(answers);
if (result.success) {
  result.data.department; // Department
  result.data.refund; // boolean
}

@typesafe-ai/sdk calls Jev directly. toJevQuestions() converts the yes/no question type from "boolean" to Jev’s native "noul"; choice and score questions pass through unchanged. Set TYPESAFE_API_KEY for the client.

Pass the returned answers to triage.decode(). The decoded object contains the fields declared in ITicketTriage; keep the original answer map if you also need Jev’s probabilities.

import { typeSafeAi } from "@ai-sdk/typesafe-ai";
import { experimental_decide } from "ai";
 
const response = await experimental_decide({
  model: typeSafeAi.decisionModel("jev-1.13.0"),
  state: ticket,
  questions: triage.questions,
});
const result = triage.decode(response.answers);
if (result.success) {
  result.data.department; // Department
  result.data.refund; // boolean
}

Vercel AI SDK’s TypeSafe provider  calls Jev through experimental_decide(). Pass triage.questions directly: the provider converts them to Jev’s native format. Decode response.answers with the same triage.decode() function.

Set TYPESAFE_AI_API_KEY for this provider, rather than the direct SDK’s TYPESAFE_API_KEY. The example uses AI SDK 7’s decision API.

import OpenAI from "openai";
 
const client = new OpenAI(); // reads OPENAI_API_KEY
const output = typia.llm.structuredOutput<ITicketTriage, { strict: true }>();
const response = await client.responses.create({
  model: "gpt-5.6-luna",
  input: [
    { role: "system", content: "Classify the customer ticket using the schema descriptions." },
    { role: "user", content: ticket },
  ],
  text: {
    format: {
      type: "json_schema",
      name: "ticket_triage",
      strict: true,
      schema: { ...output.parameters },
    },
  },
});
 
if (response.status !== "completed" || !response.output_text) {
  throw new Error("OpenAI did not return a completed structured response.");
}
const result = output.validate(JSON.parse(response.output_text));
if (result.success) {
  result.data.department; // Department
  result.data.refund; // boolean
}

OpenAI’s official openai SDK accepts JSON Schema for Structured Outputs. typia.llm.structuredOutput<ITicketTriage, { strict: true }>() generates that schema for text.format from the same type and comments. Set OPENAI_API_KEY for the client.

OpenAI returns the triage object as JSON text. The guard handles incomplete responses or refusals without text; output.validate() checks the parsed object. This path does not return Jev’s answer map or enforce the evaluation-specific probability annotations.

npm install -D ttsc typescript
npm install typia @typia/jev
 
npx ttsc              # build
npx ttsx src/index.ts # or run

Install the SDK packages for the example you use. Save the shared declarations and one SDK example in src/index.ts, and set its API key. Use ttsc or ttsx to apply typia’s compile-time transform.

── more in #ai-tools 4 stories · sorted by recency
── more on @typia 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/show-hn-jev-schema-b…] indexed:0 read:4min 2026-10-06 · —