form icon indicating copy to clipboard operation
form copied to clipboard

Union types are not handled correctly

Open AshotN opened this issue 4 months ago • 0 comments

Describe the bug

The internal types of Tanstack Form, DeepValue and DeepKeysAndValues don't handle union types correctly and seem to collapse them.

type Example = { id: string } | { id: undefined };

type Test = DeepKeysAndValues<Example>
//   ^? { key: "id"; value: string; }
const testObj: { id: string } | { id: undefined } = Math.random()
    ? { id: undefined }
    : { id: '' }

type idField = DeepValue<typeof testObj, 'id'>
// Type error - TS2322: Type undefined is not assignable to type string
const a: idField = undefined
const b: idField = 'zzz'

My use case was using a union type with withForm, this also happens with withFieldGroup

import type { MergeExclusive, RequiredDeep } from 'type-fest'

export type EditType = ContactType & ContactPatchType // ContactType has readonly properties like `id`, ContactPatchType has the properties that are editable
export type CreateType = RequiredDeep<ContactDataType> // ContactDataType contains properties that are used for initial create, so no `id` for example
type EitherType = MergeExclusive<CreateType, EditType>

export const ContactFormFields = withForm({
    defaultValues: {} as EitherType,
...

EditType contains {id: string} while CreateType does not. You would expect a form to understand that id may be string | undefined

Instead it becomes just {id: string}

Due to the incorrect type, this does not produce a type error but can fail in runtime since field.state.value may be undefined

<group.AppField name="id">
  {(field) => <div>ID: {field.state.value.length}</div>}
</group.AppField>

Your minimal, reproducible example

N/A

Steps to reproduce

^ See Above

Expected behavior

Union types to be handled properly

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

"@tanstack/react-form": "1.23.7",

TanStack Form adapter

react-form

TanStack Form version

1.23.7

TypeScript version

5.9.3

Additional context

No response

AshotN avatar Oct 20 '25 05:10 AshotN