field.infer(obj, overrides?) generates a complete form schema from an existing JavaScript object. It auto-detects field types based on key names and value types, so you can go from a plain object to a working form in one line.
The same helper is also exported as inferFromObject(obj, overrides?) when you prefer a direct utility import.
How auto-detection works:
| Strategy | Detection | Example |
|---|---|---|
| Key-based | Keys containing email, password, phone, url, bio, description, date, active, enabled, toggle, … are mapped to their matching field type | email → field.email() |
| Value-based | boolean → switch, number → number, Array → select, everything else → text | true → field.switch() |
| Labels | Keys are prettified automatically | firstName → "First name", phone_number → "Phone number" |
The returned schema can be spread and selectively overridden with explicit builders - inferred fields and hand-written fields mix freely.
| 1 | import { field } from '@runilib/react-formbridge' |
| 2 | |
| 3 | // Pass any object - field.infer reads keys + values to build the schema |
| 4 | const user = { |
| 5 | firstName: 'Ava', |
| 6 | email: 'ava@example.com', |
| 7 | age: 32, |
| 8 | active: true, |
| 9 | } |
| 10 | |
| 11 | const schema = { |
| 12 | // Infer all fields automatically |
| 13 | ...field.infer(user), |
| 14 | // Override a specific field with an explicit builder |
| 15 | email: field.email('Email').required(), |
| 16 | } |
| 17 | |
| 18 | // Result: firstName → text, email → email (overridden), |
| 19 | // age → number, active → switch |
Per-field overrides
The second argument lets you customise individual inferred fields without replacing them entirely.
Complete InferFieldOptions surface:
| Method | Type | Description |
|---|---|---|
type? | FieldType | Force a specific field type - overrides auto-detection |
label? | string | Override the generated label |
placeholder? | string | Override the generated placeholder |
hint? | string | Helper text |
required? | boolean | string | Marks the field required (message optional) |
min? | number | Minimum length/value |
max? | number | Maximum length/value |
options? | SelectOption[] | string[] | Option list for select/radio fields |
disabled? | boolean | Disable the field |
hidden? | boolean | Hide the field |
validate? | (value, allValues) => string | null | Custom inline validator |
| 1 | import { field } from '@runilib/react-formbridge' |
| 2 | |
| 3 | const product = { |
| 4 | name: '', |
| 5 | description: '', |
| 6 | price: 0, |
| 7 | category: '', |
| 8 | inStock: true, |
| 9 | } |
| 10 | |
| 11 | const schema = field.infer(product, { |
| 12 | name: { required: true, min: 2, max: 100 }, |
| 13 | description: { type: 'textarea', placeholder: 'Describe the product...' }, |
| 14 | price: { required: true, min: 0, hint: 'Price in euros' }, |
| 15 | category: { type: 'select', options: ['Electronics', 'Clothing', 'Books'] }, |
| 16 | inStock: { label: 'Available in stock' }, |
| 17 | }) |
Edit form pattern
field.infer() is ideal for edit/update forms where you already have the entity data. The object values become the default values of each field, so the form is pre-filled automatically.
| 1 | import { field, useFormBridge } from '@runilib/react-formbridge' |
| 2 | |
| 3 | function EditUserForm({ user }: { user: User }) { |
| 4 | // Schema is generated from the existing user - form is pre-filled |
| 5 | const schema = field.infer(user, { |
| 6 | email: { required: 'Email is required' }, |
| 7 | password: { hidden: true }, |
| 8 | role: { type: 'select', options: ['admin', 'user', 'viewer'] }, |
| 9 | }) |
| 10 | |
| 11 | const { Form, fields } = useFormBridge(schema) |
| 12 | |
| 13 | return ( |
| 14 | <Form onSubmit={(values) => updateUser(user.id, values)}> |
| 15 | <fields.email /> |
| 16 | <fields.role /> |
| 17 | <Form.Submit>Save user</Form.Submit> |
| 18 | </Form> |
| 19 | ) |
| 20 | } |
When to use inference vs explicit builders
Inference shines for rapid scaffolding - admin panels, CRUD tools, internal dashboards, prototypes. For production user-facing forms, explicit builders give you full control over labels, validation messages, conditional logic, and UX polish.
Auto-detection rules used by field.infer():
| Key / value shape | Inferred type |
|---|---|
Key names containing email | email |
Key names containing password / pass | password |
Key names containing phone / tel / mobile / cell / fax | phone |
Key names containing url / website / link | url |
Key names containing bio, description, note, comment | textarea |
Key names containing date, birthday, born | date |
Key names containing enabled, active, toggle, visible | switch |
boolean values | switch |
number values | number |
| array values | select |
| Everything else | text (fallback) |
Tip: start with field.infer() to bootstrap quickly, then progressively replace inferred fields with explicit builders as your form requirements grow.