JI
Skip to content
All posts
ReactMay 2, 2026·6 min read

Typing the WP REST API in a React admin

Plugin settings screens get messy fast. A small pattern for keeping REST responses the same shape every time — and typed end to end.

A plugin settings screen is a React app talking to a handful of REST endpoints. The pain starts when the PHP side returns a slightly different shape than the TypeScript side expects. Here's how I keep both honest.

Register the route with a schema

register_rest_route accepts an args schema. Fill it in. It validates input, documents the shape, and becomes the contract your TypeScript types mirror.

register_rest_route( 'portfolio/v1', '/settings', array(
  'methods'  => 'POST',
  'callback' => 'portfolio_save_settings',
  'permission_callback' => fn() => current_user_can( 'manage_options' ),
  'args' => array(
    'accent' => array( 'type' => 'string', 'required' => true ),
  ),
) );

Fetch with apiFetch, not raw fetch

@wordpress/api-fetch handles the nonce and base path for you. Wrap it once, type the return, and every call site gets autocomplete.

import apiFetch from "@wordpress/api-fetch";

interface Settings { accent: string }

export const getSettings = () =>
  apiFetch<Settings>({ path: "/portfolio/v1/settings" });

One typed wrapper per resource, one PHP schema per route. The two ends can't drift without a compiler error — which is exactly what you want at 2am.