How to get TypeScript type hints for custom components using createFormHook in TanStack Form? #1728
-
I’m trying to create a custom input component and use it with createFormHook + useAppForm, but I don’t get TypeScript type hints when I accidentally pass the wrong type. Here is my setup: // TextField.tsx
export default function TextField({ label }: { label: string }) {
const field = useFieldContext<string>() // I expect this to be typed
return (
<div>
<label>
<div>{label}</div>
<input
value={field.state.value}
onChange={(e) => field.handleChange(e.target.value)}
onBlur={field.handleBlur}
className='border'
/>
</label>
</div>
)
}
// NumberField.tsx
export default function NumberField({ label }: { label: string }) {
const field = useFieldContext<number>()
return (
<div>
<label>
<div>{label}</div>
<input
type="number"
value={field.state.value}
onChange={(e) => field.handleChange(Number(e.target.value))}
onBlur={field.handleBlur}
className='border'
/>
</label>
</div>
)
} Usage import { z } from 'zod'
import { useAppForm } from './hooks/form.tsx'
const formSchema = z.object({
string: z.string().min(1, 'String is required'),
number: z.number().min(0, 'Number must be positive'),
})
export function MyForm() {
const form = useAppForm({
defaultValues: {
string: '',
number: 0,
},
validators: { onChange: formSchema },
onSubmit: ({ value }) => console.log(value),
})
return (
<form onSubmit={(e) => { e.preventDefault(); form.handleSubmit() }}>
<form.AppField name="string">
{(field) => <field.TextField label="String" />}
</form.AppField>
{/* ⚠️⚠️⚠️⚠️⚠️⚠️ Mistake: I accidentally used TextField for a number field */}
<form.AppField name="number">
{(field) => <field.TextField label="Number" />}
</form.AppField>
<form.AppForm>
<form.SubscribeButton label="Submit" />
</form.AppForm>
</form>
)
} Problem: Questions: How can I make TypeScript provide type hints for my custom field components so that passing the wrong type triggers an IDE warning? Is there a recommended way to use createFormHook with custom components to maintain strong typing between AppField names and field values? Thank you in advance! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
When calling There's a draft PR searching for a good solution for this (likely a branded component) in #1606 As for making it restricted with the current system, you have to implement that yourself. Luckily, that's fairly straightforward: interface YourComponentProps {
field: {
state: {
// the field must have this type, we don't care about the rest
value: number
}
}
}
// You don't actually need to use the field prop passed
function YourComponent(props: YourComponentProps) {
const field = useFieldContext<number>()
// ...
}
// Usage
<field.YourComponent field={field} /> If you have feedback or suggestions for a desired API, please post a comment in #1606 ! I'm not quite satisfied with the current concept yet. |
Beta Was this translation helpful? Give feedback.
When calling
<field.YourComponent />
, it may seem like it has information aboutfield
, but it actually does not. It's the same as if you had called<YourComponent />
. The benefit of having the field autocomplete it for you is precisely that, autocompletion.There's a draft PR searching for a good solution for this (likely a branded component) in #1606
As for making it restricted with the current system, you have to implement that yourself. Luckily, that's fairly straightforward: