Type inference not working for createServerValidate with Standard Schema (Zod)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 6.7k
- Forks
- 682
- Avg merge
- 5d 18h
- Merged PRs (30d)
- 7
Description
Description
When using createServerValidate from @tanstack/react-form-start with Zod schemas (which implement Standard Schema v1), the return type is Promise<any> instead of inferring the output type from the schema.
Since TanStack Form v1.0+ supports Standard Schema natively, and Zod v4+ properly implements the Standard Schema spec with type information available via StandardSchemaV1.InferOutput, I would expect createServerValidate to infer the validated data type automatically.
Environment
@tanstack/react-form-start: 1.25.0@tanstack/form-core: 1.25.0zod: 4.1.12- TypeScript: (affects all versions)
Current Behavior
import { createServerValidate, formOptions } from '@tanstack/react-form-start';
import { z } from 'zod';
const emailFormOpts = formOptions({
defaultValues: {
email: '',
},
});
const loginSchema = z.object({
email: z.string().email(),
redirect: z.string().default('/'),
});
const serverValidate = createServerValidate({
...emailFormOpts,
onServerValidate: loginSchema,
});
// Type is inferred as Promise<any> instead of Promise<{ email: string; redirect: string }>
const validatedData = await serverValidate(formData);
// ^? any
Expected Behavior
The return type should be inferred from the Zod schema:
const validatedData = await serverValidate(formData);
// ^? { email: string; redirect: string }
Root Cause Analysis
After investigating the source code:
1. Type Definition Returns Promise<any>
From createServerValidate.d.ts:
export declare const createServerValidate: <TFormData, ...>(
defaultOpts: CreateServerValidateOptions<...>
) => (formData: FormData, info?: Parameters<typeof decode>[1]) => Promise<any>;
2. Type Information IS Available
Zod v4's Standard Schema implementation provides type information:
export interface StandardSchemaV1<Input = unknown, Output = Input> {
readonly "~standard": StandardSchemaV1.Props<Input, Output>;
}
export declare namespace StandardSchemaV1 {
export type InferOutput<Schema extends StandardSchemaV1> =
NonNullable<Schema["~standard"]["types"]>["output"];
}
3. TanStack Form Only Extracts Error Types
From @tanstack/form-core/src/FormApi.ts:
export type UnwrapFormAsyncValidateOrFn<
TValidateOrFn extends undefined | FormAsyncValidateOrFn<any>,
> = [TValidateOrFn] extends [StandardSchemaV1<any, any>]
? Record<string, StandardSchemaV1Issue[]> // Only extracts error type!
: undefined
The library only extracts validation errors from Standard Schema validators, not the output data type.
Proposed Solution
Create a utility type to extract the output type from Standard Schema validators:
type InferValidatorOutput<TValidator> =
TValidator extends StandardSchemaV1<any, infer Output>
? Output
: TValidator extends FormValidateAsyncFn<infer TFormData>
? TFormData
: unknown;
Then update createServerValidate's return type to use Promise<InferValidatorOutput<TOnServer>> instead of Promise<any>.
Current Workaround
Users must manually assert the type:
import type { StandardSchemaV1 } from 'zod';
const validatedData = await serverValidate(formData) as StandardSchemaV1.InferOutput<typeof loginSchema>;
// Or using z.infer:
const validatedData = await serverValidate(formData) as z.infer<typeof loginSchema>;
Impact
This affects all users of createServerValidate with Standard Schema validators (Zod, Valibot, ArkType, etc.). Type safety is lost at the boundary between form validation and business logic, requiring manual type assertions throughout the codebase.
Additional Context
This appears to be an oversight rather than intentional design, as:
- TanStack Form explicitly supports Standard Schema
- Standard Schema provides full type information via
~standard.types - The validated data is returned at runtime with full type information
- Only the TypeScript type definition is missing the connection
Would the maintainers be open to a PR implementing this type inference? I'm happy to contribute if this aligns with the project's direction.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in createServerValidate.d.ts, then compare its return type with Standard Schema handling in @tanstack/form-core/src/FormApi.ts. Use the included Zod example to verify that the awaited result is inferred as the schema output rather than any, while preserving the existing validator behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, developer-experience
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100