Expanding Type Support for OpenAPI Link
Because of OpenAPI Serializer limitations, values like Date and bigint are received by the client in JSON-friendly form. You can convert them back to native types on the client with either Response Validation Plugin or Smart Coercion Plugin, but only under the conditions described below.
Choose a Plugin
- Use Response Validation Plugin when you want manual control over coercion logic and can define explicit coercion rules in your schemas.
- Use Smart Coercion Plugin when you want automatic coercion based on schema instead of defining coercion logic yourself.
WARNING
These plugins can only restore types that the OpenAPI Serializer can represent. If you need additional types, extend the serializer first.
Nested Blob and File values are still limited by Bracket Notation.
Use Response Validation Plugin
Use Response Validation Plugin when you want to manually control how values are converted back to native types. The coercion rules live in your contract schemas, so the behavior stays explicit and predictable.
const contract = oc.output(z.object({
date: z.coerce.date<Date>(),
bigint: z.coerce.bigint<bigint>(),
}))
const procedure = implement(contract).handler(() => ({
date: new Date(),
bigint: 123n,
}))The server still returns JSON-friendly data:
const rawOutput = {
date: '2025-09-01T07:24:39.000Z',
bigint: '123',
}With ResponseValidationLinkPlugin, the client validates that response and applies your schema coercion before your code uses it.
const output = {
date: new Date('2025-09-01T07:24:39.000Z'),
bigint: 123n,
}Setup
Add the plugin to your link, then remove the JsonifiedClient wrapper from the client type.
import type { RouterContractClient } from '@orpc/contract'
import { ResponseValidationLinkPlugin } from '@orpc/contract/plugins'
const link = new OpenAPILink(contract, {
plugins: [
new ResponseValidationLinkPlugin(contract),
],
})
const client: JsonifiedClient<RouterContractClient<typeof contract>> = createORPCClient(link)
const client: RouterContractClient<typeof contract> = createORPCClient(link) Use Smart Coercion Plugin
Use Smart Coercion Plugin when you want the client to coerce values automatically from schema instead of adding coercion logic to each schema manually.
import type { RouterContractClient } from '@orpc/contract'
import { SmartCoercionLinkPlugin } from '@orpc/json-schema'
const link = new OpenAPILink(contract, {
plugins: [
new SmartCoercionLinkPlugin(contract),
],
})
const client: JsonifiedClient<RouterContractClient<typeof contract>> = createORPCClient(link)
const client: RouterContractClient<typeof contract> = createORPCClient(link) 
