TypeScript
Type Imports
// Core types
import type { Forma, FieldDefinition, FieldError } from "@fogpipe/forma-core";
// React types
import type {
ComponentMap,
TextComponentProps,
NumberComponentProps,
SelectComponentProps,
DisplayComponentProps,
DisplayFieldProps,
FormRendererHandle,
LayoutProps,
FieldWrapperProps,
PageWrapperProps,
} from "@fogpipe/forma-react";
Validate Spec at Compile Time
const spec = {
version: "1.0",
meta: { id: "contact", title: "Contact" },
schema: { type: "object", properties: { name: { type: "string" } } },
fields: { name: { type: "text", label: "Name" } },
fieldOrder: ["name"],
} as const satisfies Forma;
Type Form Data
interface ContactData {
name: string;
email: string;
}
const forma = useForma({
spec,
onSubmit: (data) => {
const typed = data as ContactData;
console.log(typed.name);
},
});
Type Custom Components
import type {
TextComponentProps,
NumberComponentProps,
} from "@fogpipe/forma-react";
const TextInput = ({ field }: TextComponentProps) => (
<input
value={field.value ?? ""}
onChange={(e) => field.onChange(e.target.value)}
/>
);
const components: ComponentMap = {
text: TextInput,
email: TextInput,
// TypeScript errors if props don't match expected type
};
Type Computed Values
interface OrderComputed {
subtotal: number;
tax: number;
total: number;
}
const computed = forma.computed as OrderComputed;
Display Field Types
Display field components use DisplayComponentProps, which omits value and onChange:
import type { DisplayComponentProps } from "@fogpipe/forma-react";
function DisplayField({ field }: DisplayComponentProps) {
// field.content — string | undefined (static text)
// field.sourceValue — unknown | undefined (resolved computed value)
// field.format — string | undefined (format hint)
// field.value — never (not available)
// field.onChange — never (not available)
}
Field State Types
Access readonly, adorner, and variant properties with full type safety:
import type {
TextComponentProps,
NumberComponentProps,
} from "@fogpipe/forma-react";
// Readonly and adorners are on all field props via BaseFieldProps
function TextInput({ field }: TextComponentProps) {
field.readonly; // boolean
field.prefix; // string | undefined
field.suffix; // string | undefined
field.variant; // string | undefined
field.variantConfig; // Record<string, unknown> | undefined
}
FormRenderer Ref
import type { FormRendererHandle } from "@fogpipe/forma-react";
const formRef = useRef<FormRendererHandle>(null);
formRef.current?.submitForm();
formRef.current?.focusFirstError();
const values = formRef.current?.getValues();