TypeScript Usage
mobx-react-form ships with first-class TypeScript support, providing type inference for form fields, autocomplete for field properties, and nested path autocomplete for the $() selector.
TypeScript version
>= 4.1is recommended for full support of recursive conditional types (PathsOf).
Typed Form Constructor
Use the generic type parameter F on Form<F> to describe the shape of your form values:
import { Form } from 'mobx-react-form';
interface LoginForm {
email: string;
password: string;
}
const form = new Form<LoginForm>({ ... });
// form.values() returns { email?: string; password?: string }
// form.$('email') returns Field<string>
FieldDefinition — Autocomplete for Field Props
When defining fields in unified mode, annotate the object with Record<string, FieldDefinition> to get full autocomplete on every field property:
import { Form } from 'mobx-react-form';
import type { FieldDefinition } from 'mobx-react-form';
const fields: Record<string, FieldDefinition> = {
username: {
label: 'Username', // ← autocomplete on label
value: 'SteveJobs', // ← autocomplete on value
rules: 'required|string|between:5,15', // ← autocomplete on rules
placeholder: 'Enter username',
disabled: false,
type: 'text',
autoFocus: true,
nullable: false,
autoComplete: 'username',
related: ['email'],
},
};
const form = new Form({ fields }, { name: 'MyForm' });
Available FieldDefinition Properties
| Property | Type | Description |
|---|---|---|
value |
any |
Field value |
label |
string |
Field label |
placeholder |
string |
Field placeholder |
rules |
string |
Validation rules (DVR format) |
type |
string |
Field type (default: "text") |
disabled |
boolean |
Disabled state |
related |
string[] |
Related field paths |
default |
any |
Default value (on reset) |
initial |
any |
Initial value |
bindings |
string |
Binding name |
extra |
Record<string, any> |
Extra metadata |
options |
OptionsModel |
Field-level options |
hooks |
Record<string, any> |
Event hooks |
handlers |
Record<string, any> |
Event handlers |
validators |
any[] |
VJF validation functions |
validatedWith |
string |
Prop to validate instead of value |
ref |
any |
React ref |
nullable |
boolean |
Allow null values |
autoFocus |
boolean |
Auto-focus on mount |
inputMode |
string |
Mobile keyboard mode |
autoComplete |
string |
HTML autocomplete attribute |
converter |
Function |
Value converter function |
converters |
Function[] |
Array of converter functions |
computed |
any |
Computed value function |
observers |
any[] |
MobX observers |
interceptors |
any[] |
MobX interceptors |
name |
string |
Field name (overrides key) |
class |
any |
Custom Field class |
fields |
any |
Nested sub-field definitions |
Transparent Nested Path Autocomplete
The $() method on Form<F> is typed to accept both top-level keys (keyof F) and nested paths (PathsOf<F>) automatically — no explicit type annotations needed:
interface ClubForm {
club: { name: string; city: string };
members: { firstname: string; lastname: string }[];
}
const form = new Form<ClubForm>({ ... });
form.$('club'); // ✓ autocomplete from keyof F
form.$('club.name'); // ✓ autocomplete after dot!
form.$('members[].firstname'); // ✓ array notation supported
form.$('club.unknown'); // ✗ TypeScript error — not a valid path
How It Works
The PathsOf<T> utility type recursively derives all possible field paths from a type T:
import { PathsOf } from 'mobx-react-form';
type ClubForm = {
club: { name: string; city: string };
members: { firstname: string; lastname: string }[];
};
// PathsOf<ClubForm> = "club" | "members"
// | "club.name" | "club.city"
// | "members[].firstname" | "members[].lastname"
PathsOfis integrated directly into the$()method signature — you don't need to import it for autocomplete to work.
Explicit PathsOf Usage
You can also use PathsOf explicitly in helper functions or components:
import { Form, PathsOf } from 'mobx-react-form';
import type { FieldDefinition } from 'mobx-react-form';
// Helper function with typed path
function getField<T extends Record<string, any>>(
form: Form<T>,
path: keyof T | PathsOf<T>
) {
return form.$(path as any);
}
// Typed callback for each()
form.each((field) => {
if (field.path === 'email') {
// field is typed as Field<any>
}
});
Extending Form & Field with Types
When extending classes, propagate the generic parameter:
import { Form, Field } from 'mobx-react-form';
interface MyFormValues {
email: string;
password: string;
}
class MyField extends Field {
// custom methods...
}
class MyForm extends Form<MyFormValues> {
makeField(props: any) {
return new MyField(props);
}
}
const form = new MyForm({ ... });
form.$('email'); // autocomplete works!
Typed values() Output
The values() method returns a partial object typed from the generic F parameter:
const form = new Form<LoginForm>({ ... });
const vals = form.values();
// ^? { email?: string; password?: string }
Nested object keys are flattened. For flat map values (path → value), use
form.flatMapValues.