Type inference not working for createServerValidate with Standard Schema (Zod)
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.
This issue occurs not only with Standard Schema validators but also with plain JavaScript. The root cause is a recent update to @tanstack/react-form-start, where createServerValidate was switched to use createServerFn from @tanstack/react-start to define the server validation function. As a result, generics and type inference are erased. In my tests, this problem is isolated to @tanstack/react-form-start.
https://github.com/TanStack/form/blob/5ae9c076232589dd721a8172166188870df3cc3a/packages/react-form-start/src/createServerValidate.tsx#L101