wp-rest-typegen

Generate TypeScript types straight from a live WordPress REST API — core endpoints plus your custom post types, fields, and taxonomies. Zero runtime dependencies.

npm i -D wp-rest-typegen Node ≥ 20 0 dependencies GPL-2.0-or-later

Why

WordPress already publishes a full JSON Schema for every resource (via an OPTIONS request to each route). Most projects still hand-write these types or reach for a heavy generic OpenAPI generator that knows nothing about WordPress. wp-rest-typegen reads the schema your site is already serving and emits clean, WP-aware TypeScript — including the view / edit / embed context model that generic tools miss.

Discovers everything

Core routes, custom post types, register_rest_field additions, and taxonomies — pulled from the live route index.

Context-aware

Emit view, edit, or embed shapes. Edit-only fields like title.raw appear only where they should.

Zero runtime deps

Ships as plain compiled JavaScript on Node's built-in fetch — nothing to audit, nothing to pull in.

Type-safe by construction

Enums become string-literal unions; output passes tsc --strict.

Quick start

# install as a dev dependency
npm install --save-dev wp-rest-typegen

# generate types for the wp/v2 namespace
npx wp-rest-typegen https://example.com --namespace wp/v2 -o src/types/wp.d.ts

Then import the generated types in your plugin / theme / block code:

import apiFetch from '@wordpress/api-fetch';
import type { Post } from './types/wp.d.ts';

const posts = await apiFetch<Post[]>({ path: '/wp/v2/posts' });
posts[0].status; // "publish" | "draft" | ... — autocompletes & type-checks

The context model

The same resource differs by context. WordPress exposes edit-only fields (e.g. title.raw) only under edit. wp-rest-typegen honours that:

// --context view
export interface Post {
  title: { rendered: string };
}
// --context edit
export interface Post {
  title: { raw: string; rendered: string };
}

CLI options

FlagDescription
<site-url>Site URL (positional) or --url.
--input <file>Read schemas from a local JSON dump instead of HTTP.
-o, --outOutput file (defaults to stdout).
--contextview | edit | embed (default view).
--includeComma-separated rest bases to keep.
--excludeComma-separated rest bases to drop.
--namespaceOnly routes in this namespace, e.g. wp/v2.
--header k:vExtra request header (repeatable) — e.g. for auth.
--insecureSkip TLS verification (self-signed certs, e.g. *.local).
--no-registryOmit the WPRestTypes registry interface.

Local / self-signed sites

Local by Flywheel, DevKinsta and friends serve https://*.local with a self-signed certificate that Node rejects. Target the plain-HTTP URL, or pass --insecure:

npx wp-rest-typegen https://testwp.local --insecure -o src/types/wp.d.ts

Programmatic API

import { discover, generate } from 'wp-rest-typegen';

const resources = await discover('https://example.com', { namespace: 'wp/v2' });
const dts = generate(resources, { context: 'view' });

Every run also emits a WPRestTypes interface mapping each REST base to its type — handy for generic, base-keyed fetch helpers.