The AI SDK provides model-specific type safety for modelOptions. Each model's capabilities determine which model options are allowed, and TypeScript will enforce this at compile time.
Tip: For structured outputs, most users should prefer the first-class chat({ outputSchema }) option over the raw provider text option shown below — it works across providers and validates the result for you. The raw text option is for when you need provider-specific control.
Each adapter factory captures the model literal as a type parameter — openaiText<TModel>(model) — so the adapter carries the exact model you selected at the type level.
The modelOptions you pass are then resolved against a per-model map (ResolveProviderOptions<TModel>). Each model's entry declares only the options that model actually supports. A model without a structured-output capability simply has no text property in its resolved options type, so TypeScript's excess-property checking rejects text for that model — at compile time, with zero runtime cost.
This is the same mechanism described in Typed Pre-Configured Options (which captures these resolved options in a reusable object) and Extend Adapter (which lets you attach the same typed modelOptions to custom models).
import { chat } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";
// ✅ gpt-5 supports structured outputs - `text` is allowed
const validCall = chat({
adapter: openaiText("gpt-5"),
messages: [],
modelOptions: {
// OK - text is included for gpt-5
text: {
format: {
type: "json_schema",
name: "my_schema",
schema: {
/* JSON Schema object */
},
},
},
},
});import { chat } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";
// ✅ gpt-5 supports structured outputs - `text` is allowed
const validCall = chat({
adapter: openaiText("gpt-5"),
messages: [],
modelOptions: {
// OK - text is included for gpt-5
text: {
format: {
type: "json_schema",
name: "my_schema",
schema: {
/* JSON Schema object */
},
},
},
},
});// ❌ gpt-4-turbo does NOT support structured outputs - `text` is rejected
const invalidCall = chat({
adapter: openaiText("gpt-4-turbo"),
messages: [],
modelOptions: {
text: {}, // ❌ TypeScript error: 'text' does not exist in type
},
});// ❌ gpt-4-turbo does NOT support structured outputs - `text` is rejected
const invalidCall = chat({
adapter: openaiText("gpt-4-turbo"),
messages: [],
modelOptions: {
text: {}, // ❌ TypeScript error: 'text' does not exist in type
},
});TypeScript will produce:
error TS2353: Object literal may only specify known properties, and 'text' does not exist in type ...'.error TS2353: Object literal may only specify known properties, and 'text' does not exist in type ...'.