A static form's presence and input set are fixed. A typical example is a registration form — it always appears on the registration page and its fields (email, password, nickname) are constant. Similarly, a post creation form's fields remain constant (title, content, tags).
I recommend using CreateForm with initValue or validator for type-safe static form definitions. CreateForm lets you define the form outside components.
src/shared/signUpForm.ts
export const SIGN_UP_FORM = new CreateForm({
validator: {
email: {
required: { required: true, message: "Please enter your email" },
RegExp: {
RegExp: new RegExp("^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$"),
message: "Invalid email format",
},
},
nickname: {
required: { required: true, message: "Please enter your nickname" },
minLength: { number: 2, message: "Nickname must be at least 2 characters" },
maxLength: { number: 10, message: "Nickname must be 10 characters or less" },
},
password: {
required: { required: true, message: "Please enter your password" },
minLength: { number: 8, message: "Password must be at least 8 characters" },
maxLength: { number: 16, message: "Password must be 16 characters or less" },
RegExp: [
{
RegExp: new RegExp("^[^\s]+$"),
message: "Password cannot contain spaces",
},
{
RegExp: new RegExp("^(?=.*[a-z])(?=.*\d)(?=.*[@$!%*?&])[a-z\d@$!%*?&]+$"),
message: "Password must contain lowercase letters, numbers, and special characters",
},
],
},
passwordConfirm: {
required: { required: true, message: "Please enter your password" },
minLength: { number: 8, message: "Password must be at least 8 characters" },
maxLength: { number: 16, message: "Password must be 16 characters or less" },
RegExp: [
{
RegExp: new RegExp("^[^\s]+$"),
message: "Password cannot contain spaces",
},
{
RegExp: new RegExp("^(?=.*[a-z])(?=.*\d)(?=.*[@$!%*?&])[a-z\d@$!%*?&]+$"),
message: "Password must contain lowercase letters, numbers, and special characters",
},
],
custom: {
checkFn: (value: string, store: { password: unknown }) => value !== store.password,
message: "Passwords do not match",
},
},
"Check terms and conditions": {
checked: { checked: false, message: "Please agree to the terms and conditions" },
}
},
validateOn: ["submit", "change"],
clearFormOn: ["submit", "routeChange"]
});
Defining the form spec externally separates concerns: UI components handle rendering while validation logic lives elsewhere, improving readability and maintainability.