Skip to main content

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();