diff --git a/packages/core-data/README.md b/packages/core-data/README.md
index 09353c16ad491..fc07ff9df8f6c 100644
--- a/packages/core-data/README.md
+++ b/packages/core-data/README.md
@@ -1,6 +1,6 @@
# Core Data
-Core Data is a [data module](https://github.com/WordPress/gutenberg/tree/HEAD/packages/data/README.md) intended to simplify access to and manipulation of core WordPress entities. It registers its own store and provides a number of selectors which resolve data from the WordPress REST API automatically, along with dispatching action creators to manipulate data.
+Core Data is a [data module](https://github.com/WordPress/gutenberg/tree/HEAD/packages/data/README.md) intended to simplify access to and manipulation of core WordPress entities. It registers its own store and provides a number of selectors which resolve data from the WordPress REST API automatically, along with dispatching action creators to manipulate data. Core data is shipped with [`TypeScript definitions for WordPress data types`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/core-data/src/types/README.md).
Used in combination with features of the data module such as [`subscribe`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/data/README.md#subscribe-function) or [higher-order components](https://github.com/WordPress/gutenberg/tree/HEAD/packages/data/README.md#higher-order-components), it enables a developer to easily add data into the logic and display of their plugin.
diff --git a/packages/core-data/src/index.js b/packages/core-data/src/index.js
index 876849704012e..68ed31a7c5586 100644
--- a/packages/core-data/src/index.js
+++ b/packages/core-data/src/index.js
@@ -77,3 +77,4 @@ export { default as __experimentalUseEntityRecord } from './hooks/use-entity-rec
export { default as __experimentalUseEntityRecords } from './hooks/use-entity-records';
export * from './entity-provider';
export * from './fetch';
+export * from './types';
diff --git a/packages/core-data/src/types/README.md b/packages/core-data/src/types/README.md
new file mode 100644
index 0000000000000..10d2a2be75e63
--- /dev/null
+++ b/packages/core-data/src/types/README.md
@@ -0,0 +1,193 @@
+# Entity Records Types
+
+## Overview
+
+The types in this directory are designed to support the following use-cases:
+
+* Provide type-hinting and documentation for entity records fetched in the various REST API contexts.
+* Type-check the values we use to *edit* entity records, the values that are sent back to the server as updates.
+
+**Warning:** The types model the expected API responses which is **not** the same as having a full type safety for the API-related operations. The API responses are type-cast to these definitions and therefore may not match those expectations; for example, a plugin could modify the response, or the API endpoint could have a nuanced implementation in which strings are sometimes used instead of numbers.
+
+### Context-aware type checks for entity records
+
+WordPress REST API returns different responses based on the `context` query parameter, which typically is one of `view`, `edit`, or `embed`. See the [REST API documentation](https://developer.wordpress.org/rest-api/) to learn more.
+
+For example, requesting `/wp/v2/posts/1?context=view` yields:
+
+```js
+{
+ "content": {
+ "protected": false,
+ "rendered": "\n
Welcome to WordPress. This is your first post. Edit or delete it, then start writing!
\n"
+ },
+ "title": {
+ "rendered": "Hello world!"
+ }
+ // other fields
+}
+```
+
+While requesting `/wp/v2/posts/1?context=edit`, yields:
+
+```js
+{
+ "content": {
+ "block_version": 1,
+ "protected": false,
+ "raw": "\nWelcome to WordPress. This is your first post. Edit or delete it, then start writing!
\n",
+ "rendered": "\nWelcome to WordPress. This is your first post. Edit or delete it, then start writing!
\n"
+ },
+ "title": {
+ "raw": "Hello world!",
+ "rendered": "Hello world!"
+ }
+ // other fields
+}
+```
+
+And, finally, requesting `/wp/v2/posts/1?context=embed` yields:
+
+```js
+{
+ // Note content is missing
+ "title": {
+ "rendered": "Hello world!"
+ }
+ // other fields
+}
+```
+
+These contexts are supported by the core-data resolvers like `getEntityRecord()` and `getEntityRecords()` to retrieve the appropriate "flavor" of the data.
+
+The types describing different entity records must thus be aware of the relevant API context. This is implemented using the `Context` type parameter. For example, the implementation of the `Post` type resembles the following snippet:
+
+```ts
+interface Post {
+ /**
+ * A named status for the post.
+ */
+ status: ContextualField< PostStatus, 'view' | 'edit', C >;
+
+ // ... other fields ...
+}
+```
+
+The `status` field is a `PostStatus` when the requesting context is `view` or `edit`, but if requested with an `embed` context the field won't appear on the `Post` object at all.
+
+### Static type checks for *edited* entity records, where certain fields become strings instead of objects.
+
+When the `post` is retrieved using `getEntityRecord`, its `content` field is an object:
+
+```js
+const post = wp.data.select('core').getEntityRecord( 'postType', 'post', 1, { context: 'view' } )
+// `post.content` is an object with two fields: protected and rendered
+```
+
+The block markup stored in `content` can only be rendered on the server so the REST API exposes both the raw markup and the rendered version. For example, `content.rendered` could used as a visual preview, and `content.raw` could be used to populate the code editor.
+
+When updating that field from the JavaScript code, however, all we can set is the raw value that the server will eventually render. The API expects us to send a much simpler `string` form which is the raw form that needs to be stored in the database.
+
+The types reflect this through the `Updatable` wrapper:
+
+```ts
+interface Post< C extends Context > {
+ title: {
+ raw: string;
+ rendered: string;
+ }
+}
+
+const post : Post< 'edit' > = ...
+// post.title is an object with properties `raw` and `rendered`
+
+const post : Updatable> = ...
+// post.title is a string
+```
+
+The `getEditedEntityRecord` selector returns the Updatable version of the entity records:
+
+```js
+const post = wp.data.select('core').getEditedEntityRecord( 'postType', 'post', 1 );
+// `post.content` is a string
+```
+
+## Helpers
+
+### Context
+
+The REST API context parameter.
+
+### ContextualField
+
+`ContextualField` makes the field available only in the specified given contexts, and ensure the field is absent from the object when in a different context.
+
+Example:
+
+```ts
+interface Post< C extends Context > {
+ …
+ modified: ContextualField< string, 'edit' | 'view', C >;
+ password: ContextualField< string, 'edit', C >;
+ …
+}
+
+const post: Post<'edit'> = …
+// post.modified exists as a string
+// post.password exists as a string
+
+const post: Post<'view'> = …
+// post.modified still exists as a string
+// post.password is missing, undefined, because we're not in the `edit` context.
+```
+
+### OmitNevers
+
+Removes all the properties of type never, even the deeply nested ones.
+
+```ts
+type MyType = {
+ foo: string;
+ bar: never;
+ nested: {
+ foo: string;
+ bar: never;
+ }
+}
+const x = {} as OmitNevers;
+// x is of type { foo: string; nested: { foo: string; }}
+// The `never` properties were removed entirely
+```
+
+### Updatable
+
+Updatable is a type describing Edited Entity Records. They are like
+regular Entity Records, but they have all the local edits applied on top of the REST API data.
+
+This turns certain field from an object into a string.
+
+Entities like Post have fields that only be rendered on the server, like title, excerpt,
+and content. The REST API exposes both the raw markup and the rendered version of those fields.
+For example, in the block editor, content.rendered could used as a visual preview, and
+content.raw could be used to populate the code editor.
+
+When updating these rendered fields, JavaScript is not be able to properly render arbitrary block
+markup. Therefore, it stores only the raw markup without the rendered part. And since that's a string,
+the entire field becomes a string.
+
+```ts
+type Post< C extends Context > {
+ title: RenderedText< C >;
+}
+const post = {} as Post;
+// post.title is an object with raw and rendered properties
+
+const updatablePost = {} as Updatable< Post >;
+// updatablePost.title is a string
+```
+
+### RenderedText
+
+A string that the server renders which often involves modifications from the raw source string.
+
+For example, block HTML with the comment delimiters exists in `post_content` but those comments are stripped out when rendering to a page view. Similarly, plugins might modify content or replace shortcodes.
diff --git a/packages/core-data/src/types/attachment.ts b/packages/core-data/src/types/attachment.ts
new file mode 100644
index 0000000000000..4ad94226f0a87
--- /dev/null
+++ b/packages/core-data/src/types/attachment.ts
@@ -0,0 +1,146 @@
+/**
+ * Internal dependencies
+ */
+import {
+ Context,
+ ContextualField,
+ MediaType,
+ PostStatus,
+ RenderedText,
+ OmitNevers,
+ CommentingStatus,
+ PingStatus,
+} from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface Attachment< C extends Context > {
+ /**
+ * The date the post was published, in the site's timezone.
+ */
+ date: string | null;
+ /**
+ * The date the post was published, as GMT.
+ */
+ date_gmt: ContextualField< string | null, 'view' | 'edit', C >;
+ /**
+ * The globally unique identifier for the post.
+ */
+ guid: ContextualField< RenderedText< C >, 'view' | 'edit', C >;
+ /**
+ * Unique identifier for the post.
+ */
+ id: number;
+ /**
+ * URL to the post.
+ */
+ link: string;
+ /**
+ * The date the post was last modified, in the site's timezone.
+ */
+ modified: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * The date the post was last modified, as GMT.
+ */
+ modified_gmt: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * An alphanumeric identifier for the post unique to its type.
+ */
+ slug: string;
+ /**
+ * A named status for the post.
+ */
+ status: ContextualField< PostStatus, 'view' | 'edit', C >;
+ /**
+ * Type of post.
+ */
+ type: string;
+ /**
+ * Permalink template for the post.
+ */
+ permalink_template: ContextualField< string, 'edit', C >;
+ /**
+ * Slug automatically generated from the post title.
+ */
+ generated_slug: ContextualField< string, 'edit', C >;
+ /**
+ * The title for the post.
+ */
+ title: RenderedText< C >;
+ /**
+ * The ID for the author of the post.
+ */
+ author: number;
+ /**
+ * Whether or not comments are open on the post.
+ */
+ comment_status: ContextualField<
+ CommentingStatus,
+ 'view' | 'edit',
+ C
+ >;
+ /**
+ * Whether or not the post can be pinged.
+ */
+ ping_status: ContextualField< PingStatus, 'view' | 'edit', C >;
+ /**
+ * Meta fields.
+ */
+ meta: ContextualField<
+ Record< string, string >,
+ 'view' | 'edit',
+ C
+ >;
+ /**
+ * The theme file to use to display the post.
+ */
+ template: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * Alternative text to display when attachment is not displayed.
+ */
+ alt_text: string;
+ /**
+ * The attachment caption.
+ */
+ caption: ContextualField< string, 'edit', C >;
+ /**
+ * The attachment description.
+ */
+ description: ContextualField<
+ RenderedText< C >,
+ 'view' | 'edit',
+ C
+ >;
+ /**
+ * Attachment type.
+ */
+ media_type: MediaType;
+ /**
+ * The attachment MIME type.
+ */
+ mime_type: string;
+ /**
+ * Details about the media file, specific to its type.
+ */
+ media_details: Record< string, string >;
+ /**
+ * The ID for the associated post of the attachment.
+ */
+ post: ContextualField< number, 'view' | 'edit', C >;
+ /**
+ * URL to the original attachment file.
+ */
+ source_url: string;
+ /**
+ * List of the missing image sizes of the attachment.
+ */
+ missing_image_sizes: ContextualField< string[], 'edit', C >;
+ }
+ }
+}
+
+export type Attachment< C extends Context > = OmitNevers<
+ _BaseEntityTypes.Attachment< C >
+>;
diff --git a/packages/core-data/src/types/base-entity-types.ts b/packages/core-data/src/types/base-entity-types.ts
new file mode 100644
index 0000000000000..790eaa63cfc9d
--- /dev/null
+++ b/packages/core-data/src/types/base-entity-types.ts
@@ -0,0 +1,36 @@
+/**
+ * This module exists solely to make the BaseEntityTypes namespace extensible
+ * with declaration merging:
+ *
+ * ```ts
+ * declare module './base-entity-types' {
+ * export namespace BaseEntityTypes {
+ * export interface Comment< C extends Context > {
+ * id: number;
+ * // ...
+ * }
+ * }
+ * }
+ * ```
+ *
+ * The huge upside is that consumers of @wordpress/core-data may extend the
+ * exported data types using interface merging as follows:
+ *
+ * ```ts
+ * import type { Context } from '@wordpress/core-data';
+ * declare module '@wordpress/core-data' {
+ * export namespace BaseEntityTypes {
+ * export interface Comment< C extends Context > {
+ * numberOfViews: number;
+ * }
+ * }
+ * }
+ *
+ * import type { Comment } from '@wordpress/core-data';
+ * const c : Comment< 'view' > = ...;
+ *
+ * // c.numberOfViews is a number
+ * // c.id is still present
+ * ```
+ */
+export namespace BaseEntityTypes {}
diff --git a/packages/core-data/src/types/comment.ts b/packages/core-data/src/types/comment.ts
new file mode 100644
index 0000000000000..56cd559780770
--- /dev/null
+++ b/packages/core-data/src/types/comment.ts
@@ -0,0 +1,96 @@
+/**
+ * Internal dependencies
+ */
+import {
+ AvatarUrls,
+ Context,
+ ContextualField,
+ OmitNevers,
+ RenderedText,
+} from './helpers';
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+export type CommentStatus = 'hold' | 'approve' | 'spam' | 'trash' | '1' | '0';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface Comment< C extends Context > {
+ /**
+ * Unique identifier for the comment.
+ */
+ id: number;
+ /**
+ * The ID of the user object, if author was a user.
+ */
+ author: number;
+ /**
+ * Email address for the comment author.
+ */
+ author_email: ContextualField< string, 'edit', C >;
+ /**
+ * IP address for the comment author.
+ */
+ author_ip: ContextualField< string, 'edit', C >;
+ /**
+ * Display name for the comment author.
+ */
+ author_name: string;
+ /**
+ * URL for the comment author.
+ */
+ author_url: string;
+ /**
+ * User agent for the comment author.
+ */
+ author_user_agent: ContextualField< string, 'edit', C >;
+ /**
+ * The content for the comment.
+ */
+ content: RenderedText< C >;
+ /**
+ * The date the comment was published, in the site's timezone.
+ */
+ date: string;
+ /**
+ * The date the comment was published, as GMT.
+ */
+ date_gmt: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * URL to the comment.
+ */
+ link: string;
+ /**
+ * The ID for the parent of the comment.
+ */
+ parent: number;
+ /**
+ * The ID of the associated post object.
+ */
+ post: ContextualField< number, 'view' | 'edit', C >;
+ /**
+ * State of the comment.
+ */
+ status: ContextualField< CommentStatus, 'view' | 'edit', C >;
+ /**
+ * Type of the comment.
+ */
+ type: string;
+ /**
+ * Avatar URLs for the comment author.
+ */
+ author_avatar_urls: AvatarUrls;
+ /**
+ * Meta fields.
+ */
+ meta: ContextualField<
+ Record< string, string >,
+ 'view' | 'edit',
+ C
+ >;
+ }
+ }
+}
+
+export type Comment< C extends Context > = OmitNevers<
+ _BaseEntityTypes.Comment< C >
+>;
diff --git a/packages/core-data/src/types/helpers.ts b/packages/core-data/src/types/helpers.ts
new file mode 100644
index 0000000000000..e3e60489bdaaf
--- /dev/null
+++ b/packages/core-data/src/types/helpers.ts
@@ -0,0 +1,153 @@
+/**
+ * Internal dependencies
+ */
+import { EntityRecord } from './index';
+
+export interface AvatarUrls {
+ /**
+ * Avatar URL with image size of 24 pixels.
+ */
+ '24': string;
+ /**
+ * Avatar URL with image size of 48 pixels.
+ */
+ '48': string;
+ /**
+ * Avatar URL with image size of 96 pixels.
+ */
+ '96': string;
+}
+
+export type MediaType = 'image' | 'file';
+export type CommentingStatus = 'open' | 'closed';
+export type PingStatus = 'open' | 'closed';
+export type PostStatus = 'publish' | 'future' | 'draft' | 'pending' | 'private';
+export type PostFormat =
+ | 'standard'
+ | 'aside'
+ | 'chat'
+ | 'gallery'
+ | 'link'
+ | 'image'
+ | 'quote'
+ | 'status'
+ | 'video'
+ | 'audio';
+
+/**
+ * The REST API context parameter.
+ */
+export type Context = 'view' | 'edit' | 'embed';
+
+/**
+ * ContextualField makes the field available only in the specified given contexts,
+ * and ensure the field is absent from the object when in a different context.
+ *
+ * @example
+ * ```ts
+ * interface Post< C extends Context > {
+ * …
+ * modified: ContextualField< string, 'edit' | 'view', C >;
+ * password: ContextualField< string, 'edit', C >;
+ * …
+ * }
+ *
+ * const post: Post<'edit'> = …
+ * // post.modified exists as a string
+ * // post.password exists as a string
+ *
+ * const post: Post<'view'> = …
+ * // post.modified still exists as a string
+ * // post.password is missing, undefined, because we're not in the `edit` context.
+ * ```
+ */
+export type ContextualField<
+ FieldType,
+ AvailableInContexts extends Context,
+ C extends Context
+> = AvailableInContexts extends C ? FieldType : never;
+
+/**
+ * Removes all the properties of type never, even the deeply nested ones.
+ *
+ * @example
+ * ```ts
+ * type MyType = {
+ * foo: string;
+ * bar: never;
+ * nested: {
+ * foo: string;
+ * bar: never;
+ * }
+ * }
+ * const x = {} as OmitNevers;
+ * // x is of type { foo: string; nested: { foo: string; }}
+ * // The `never` properties were removed entirely
+ * ```
+ */
+export type OmitNevers<
+ T,
+ Nevers = {
+ [ K in keyof T ]: Exclude< T[ K ], undefined > extends never
+ ? never
+ : T[ K ] extends Record< string, unknown >
+ ? OmitNevers< T[ K ] >
+ : T[ K ];
+ }
+> = Pick<
+ Nevers,
+ {
+ [ K in keyof Nevers ]: Nevers[ K ] extends never ? never : K;
+ }[ keyof Nevers ]
+>;
+
+/**
+ * A string that the server renders which often involves
+ * modifications from the raw source string.
+ *
+ * For example, block HTML with the comment delimiters exists
+ * in `post_content` but those comments are stripped out when
+ * rendering to a page view. Similarly, plugins might modify
+ * content or replace shortcodes.
+ */
+export interface RenderedText< C extends Context > {
+ /**
+ * The source string which will be rendered on page views.
+ */
+ raw: ContextualField< string, 'edit', C >;
+ /**
+ * The output of the raw source after processing and filtering on the server.
+ */
+ rendered: string;
+}
+
+/**
+ * Updatable is a type describing Edited Entity Records. They are like
+ * regular Entity Records, but they have all the local edits applied on top of the REST API data.
+ *
+ * This turns certain field from an object into a string.
+ *
+ * Entities like Post have fields that only be rendered on the server, like title, excerpt,
+ * and content. The REST API exposes both the raw markup and the rendered version of those fields.
+ * For example, in the block editor, content.rendered could used as a visual preview, and
+ * content.raw could be used to populate the code editor.
+ *
+ * When updating these rendered fields, Javascript is not be able to properly render arbitrary block
+ * markup. Therefore, it stores only the raw markup without the rendered part. And since that's a string,
+ * the entire field becomes a string.
+ *
+ * @example
+ * ```ts
+ * type Post< C extends Context > {
+ * title: RenderedText< C >;
+ * }
+ * const post = {} as Post;
+ * // post.title is an object with raw and rendered properties
+ *
+ * const updatablePost = {} as Updatable< Post >;
+ * // updatablePost.title is a string
+ * ```
+ */
+export type Updatable< T extends EntityRecord< 'edit' > > = {
+ [ K in keyof T ]: T[ K ] extends RenderedText< any > ? string : T[ K ];
+};
diff --git a/packages/core-data/src/types/index.ts b/packages/core-data/src/types/index.ts
new file mode 100644
index 0000000000000..80a173862b58a
--- /dev/null
+++ b/packages/core-data/src/types/index.ts
@@ -0,0 +1,72 @@
+/**
+ * Internal dependencies
+ */
+import type { Attachment } from './attachment';
+import type { Comment } from './comment';
+import type { MenuLocation } from './menu-location';
+import type { NavMenu } from './nav-menu';
+import type { NavMenuItem } from './nav-menu-item';
+import type { NavigationArea } from './navigation-area';
+import type { Page } from './page';
+import type { Plugin } from './plugin';
+import type { Post } from './post';
+import type { Settings } from './settings';
+import type { Sidebar } from './sidebar';
+import type { Taxonomy } from './taxonomy';
+import type { Theme } from './theme';
+import type { User } from './user';
+import type { Type } from './type';
+import type { Widget } from './widget';
+import type { WidgetType } from './widget-type';
+import type { WpTemplate } from './wp-template';
+import type { WpTemplatePart } from './wp-template-part';
+import type { Context, Updatable } from './helpers';
+
+export type { BaseEntityTypes } from './base-entity-types';
+
+export type {
+ Context,
+ Updatable,
+ Attachment,
+ Comment,
+ MenuLocation,
+ NavMenu,
+ NavMenuItem,
+ NavigationArea,
+ Page,
+ Plugin,
+ Post,
+ Settings,
+ Sidebar,
+ Taxonomy,
+ Theme,
+ User,
+ Type,
+ Widget,
+ WidgetType,
+ WpTemplate,
+ WpTemplatePart,
+};
+
+export type EntityRecord< C extends Context > =
+ | Attachment< C >
+ | Comment< C >
+ | MenuLocation< C >
+ | NavMenu< C >
+ | NavMenuItem< C >
+ | NavigationArea< C >
+ | Page< C >
+ | Plugin< C >
+ | Post< C >
+ | Settings< C >
+ | Sidebar< C >
+ | Taxonomy< C >
+ | Theme< C >
+ | Type< C >
+ | User< C >
+ | Widget< C >
+ | WidgetType< C >
+ | WpTemplate< C >
+ | WpTemplatePart< C >;
+
+export type UpdatableEntityRecord = Updatable< EntityRecord< 'edit' > >;
diff --git a/packages/core-data/src/types/menu-location.ts b/packages/core-data/src/types/menu-location.ts
new file mode 100644
index 0000000000000..71fb5abab8714
--- /dev/null
+++ b/packages/core-data/src/types/menu-location.ts
@@ -0,0 +1,29 @@
+/**
+ * Internal dependencies
+ */
+import { Context, OmitNevers } from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface MenuLocation< C extends Context > {
+ /**
+ * The name of the menu location.
+ */
+ name: string;
+ /**
+ * The description of the menu location.
+ */
+ description: string;
+ /**
+ * The ID of the assigned menu.
+ */
+ menu: number;
+ }
+ }
+}
+
+export type MenuLocation< C extends Context > = OmitNevers<
+ _BaseEntityTypes.MenuLocation< C >
+>;
diff --git a/packages/core-data/src/types/nav-menu-item.ts b/packages/core-data/src/types/nav-menu-item.ts
new file mode 100644
index 0000000000000..dab6b9ffad2f2
--- /dev/null
+++ b/packages/core-data/src/types/nav-menu-item.ts
@@ -0,0 +1,106 @@
+/**
+ * Internal dependencies
+ */
+import { RenderedText, Context, ContextualField, OmitNevers } from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+export type NavMenuItemType =
+ | 'taxonomy'
+ | 'post_type'
+ | 'post_type_archive'
+ | 'custom';
+export type NavMenuItemStatus =
+ | 'publish'
+ | 'future'
+ | 'draft'
+ | 'pending'
+ | 'private';
+export type Target = '_blank' | '';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface NavMenuItem< C extends Context > {
+ /**
+ * The title for the object.
+ */
+ title: RenderedText< C >;
+ /**
+ * Unique identifier for the object.
+ */
+ id: number;
+ /**
+ * The singular label used to describe this type of menu item.
+ */
+ type_label: string;
+ /**
+ * The family of objects originally represented, such as "post_type" or "taxonomy".
+ */
+ type: NavMenuItemType;
+ /**
+ * A named status for the object.
+ */
+ status: NavMenuItemStatus;
+ /**
+ * The ID for the parent of the object.
+ */
+ parent: number;
+ /**
+ * Text for the title attribute of the link element for this menu item.
+ */
+ attr_title: string;
+ /**
+ * Class names for the link element of this menu item.
+ */
+ classes: string[];
+ /**
+ * The description of this menu item.
+ */
+ description: string;
+ /**
+ * The DB ID of the nav_menu_item that is this item's menu parent, if any, otherwise 0.
+ */
+ menu_order: number;
+ /**
+ * The type of object originally represented, such as "category", "post", or "attachment".
+ */
+ object: string;
+ /**
+ * The database ID of the original object this menu item represents, for example the ID for posts or the term_id for categories.
+ */
+ object_id: number;
+ /**
+ * The target attribute of the link element for this menu item.
+ */
+ target: Target;
+ /**
+ * The URL to which this menu item points.
+ */
+ url: string;
+ /**
+ * The XFN relationship expressed in the link of this menu item.
+ */
+ xfn: string[];
+ /**
+ * Whether the menu item represents an object that no longer exists.
+ */
+ invalid: boolean;
+ /**
+ * The terms assigned to the object in the nav_menu taxonomy.
+ */
+ menus: ContextualField< number, 'view' | 'edit', C >;
+ /**
+ * Meta fields.
+ */
+ meta: ContextualField<
+ Record< string, string >,
+ 'view' | 'edit',
+ C
+ >;
+ }
+ }
+}
+
+export type NavMenuItem< C extends Context > = OmitNevers<
+ _BaseEntityTypes.NavMenuItem< C >
+>;
diff --git a/packages/core-data/src/types/nav-menu.ts b/packages/core-data/src/types/nav-menu.ts
new file mode 100644
index 0000000000000..aa3417ddba04b
--- /dev/null
+++ b/packages/core-data/src/types/nav-menu.ts
@@ -0,0 +1,53 @@
+/**
+ * Internal dependencies
+ */
+import { Context, ContextualField, OmitNevers } from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface NavMenu< C extends Context > {
+ /**
+ * Unique identifier for the term.
+ */
+ id: number;
+ /**
+ * HTML description of the term.
+ */
+ description: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * HTML title for the term.
+ */
+ name: string;
+ /**
+ * An alphanumeric identifier for the term unique to its type.
+ */
+ slug: string;
+ /**
+ * Meta fields.
+ */
+ meta: ContextualField<
+ Record< string, string >,
+ 'view' | 'edit',
+ C
+ >;
+ /**
+ * The locations assigned to the menu.
+ */
+ locations: ContextualField< string[], 'view' | 'edit', C >;
+ /**
+ * The DB ID of the original object this menu item represents, e . g . ID for posts and term_id for categories.
+ */
+ object_id: number;
+ /**
+ * Whether to automatically add top level pages to this menu.
+ */
+ auto_add: ContextualField< boolean, 'view' | 'edit', C >;
+ }
+ }
+}
+
+export type NavMenu< C extends Context > = OmitNevers<
+ _BaseEntityTypes.NavMenu< C >
+>;
diff --git a/packages/core-data/src/types/navigation-area.ts b/packages/core-data/src/types/navigation-area.ts
new file mode 100644
index 0000000000000..ed5ae88769207
--- /dev/null
+++ b/packages/core-data/src/types/navigation-area.ts
@@ -0,0 +1,29 @@
+/**
+ * Internal dependencies
+ */
+import { Context, OmitNevers } from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface NavigationArea< C extends Context > {
+ /**
+ * The name of the navigation area.
+ */
+ name: string;
+ /**
+ * The description of the navigation area.
+ */
+ description: string;
+ /**
+ * The ID of the assigned navigation.
+ */
+ navigation: number;
+ }
+ }
+}
+
+export type NavigationArea< C extends Context > = OmitNevers<
+ _BaseEntityTypes.NavigationArea< C >
+>;
diff --git a/packages/core-data/src/types/page.ts b/packages/core-data/src/types/page.ts
new file mode 100644
index 0000000000000..eb95206b8424e
--- /dev/null
+++ b/packages/core-data/src/types/page.ts
@@ -0,0 +1,144 @@
+/**
+ * Internal dependencies
+ */
+import {
+ CommentingStatus,
+ Context,
+ ContextualField,
+ PingStatus,
+ PostStatus,
+ RenderedText,
+ OmitNevers,
+} from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface Page< C extends Context > {
+ /**
+ * The date the post was published, in the site's timezone.
+ */
+ date: string | null;
+ /**
+ * The date the post was published, as GMT.
+ */
+ date_gmt: ContextualField< string | null, 'view' | 'edit', C >;
+ /**
+ * The globally unique identifier for the post.
+ */
+ guid: ContextualField< RenderedText< C >, 'view' | 'edit', C >;
+ /**
+ * Unique identifier for the post.
+ */
+ id: number;
+ /**
+ * URL to the post.
+ */
+ link: string;
+ /**
+ * The date the post was last modified, in the site's timezone.
+ */
+ modified: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * The date the post was last modified, as GMT.
+ */
+ modified_gmt: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * An alphanumeric identifier for the post unique to its type.
+ */
+ slug: string;
+ /**
+ * A named status for the post.
+ */
+ status: ContextualField< PostStatus, 'view' | 'edit', C >;
+ /**
+ * Type of post.
+ */
+ type: string;
+ /**
+ * A password to protect access to the content and excerpt.
+ */
+ password: ContextualField< string, 'edit', C >;
+ /**
+ * Permalink template for the post.
+ */
+ permalink_template: ContextualField< string, 'edit', C >;
+ /**
+ * Slug automatically generated from the post title.
+ */
+ generated_slug: ContextualField< string, 'edit', C >;
+ /**
+ * The ID for the parent of the post.
+ */
+ parent: ContextualField< number, 'view' | 'edit', C >;
+ /**
+ * The title for the post.
+ */
+ title: RenderedText< C >;
+ /**
+ * The content for the post.
+ */
+ content: ContextualField<
+ RenderedText< C > & {
+ /**
+ * Whether the content is protected with a password.
+ */
+ is_protected: boolean;
+ /**
+ * Version of the content block format used by the page.
+ */
+ block_version: ContextualField< string, 'edit', C >;
+ },
+ 'view' | 'edit',
+ C
+ >;
+ /**
+ * The ID for the author of the post.
+ */
+ author: number;
+ /**
+ * The excerpt for the post.
+ */
+ excerpt: RenderedText< C > & {
+ protected: boolean;
+ };
+ /**
+ * The ID of the featured media for the post.
+ */
+ featured_media: number;
+ /**
+ * Whether or not comments are open on the post.
+ */
+ comment_status: ContextualField<
+ CommentingStatus,
+ 'view' | 'edit',
+ C
+ >;
+ /**
+ * Whether or not the post can be pinged.
+ */
+ ping_status: ContextualField< PingStatus, 'view' | 'edit', C >;
+ /**
+ * The order of the post in relation to other posts.
+ */
+ menu_order: ContextualField< number, 'view' | 'edit', C >;
+ /**
+ * Meta fields.
+ */
+ meta: ContextualField<
+ Record< string, string >,
+ 'view' | 'edit',
+ C
+ >;
+ /**
+ * The theme file to use to display the post.
+ */
+ template: ContextualField< string, 'view' | 'edit', C >;
+ }
+ }
+}
+
+export type Page< C extends Context > = OmitNevers<
+ _BaseEntityTypes.Page< C >
+>;
diff --git a/packages/core-data/src/types/plugin.ts b/packages/core-data/src/types/plugin.ts
new file mode 100644
index 0000000000000..968f71f7a5bb7
--- /dev/null
+++ b/packages/core-data/src/types/plugin.ts
@@ -0,0 +1,74 @@
+/**
+ * Internal dependencies
+ */
+import { Context, ContextualField, RenderedText, OmitNevers } from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface Plugin< C extends Context > {
+ /**
+ * The plugin file.
+ */
+ plugin: string;
+ /**
+ * The plugin activation status.
+ */
+ status: PluginStatus;
+ /**
+ * The plugin name.
+ */
+ name: string;
+ /**
+ * The plugin's website address.
+ */
+ plugin_uri: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * The plugin author.
+ */
+ author: ContextualField<
+ Record< string, string >,
+ 'view' | 'edit',
+ C
+ >;
+ /**
+ * Plugin author's website address.
+ */
+ author_uri: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * The plugin description.
+ */
+ description: ContextualField<
+ RenderedText< 'edit' >,
+ 'view' | 'edit',
+ C
+ >;
+ /**
+ * The plugin version number.
+ */
+ version: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * Whether the plugin can only be activated network-wide.
+ */
+ network_only: boolean;
+ /**
+ * Minimum required version of WordPress.
+ */
+ requires_wp: string;
+ /**
+ * Minimum required version of PHP.
+ */
+ requires_php: string;
+ /**
+ * The plugin's text domain.
+ */
+ textdomain: ContextualField< string, 'view' | 'edit', C >;
+ }
+ }
+}
+
+export type PluginStatus = 'active' | 'inactive';
+export type Plugin< C extends Context > = OmitNevers<
+ _BaseEntityTypes.Plugin< C >
+>;
diff --git a/packages/core-data/src/types/post.ts b/packages/core-data/src/types/post.ts
new file mode 100644
index 0000000000000..2c7ed4287f183
--- /dev/null
+++ b/packages/core-data/src/types/post.ts
@@ -0,0 +1,153 @@
+/**
+ * Internal dependencies
+ */
+import {
+ CommentingStatus,
+ Context,
+ ContextualField,
+ PingStatus,
+ PostFormat,
+ PostStatus,
+ RenderedText,
+ OmitNevers,
+} from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface Post< C extends Context > {
+ /**
+ * The date the post was published, in the site's timezone.
+ */
+ date: string | null;
+ /**
+ * The date the post was published, as GMT.
+ */
+ date_gmt: ContextualField< string | null, 'view' | 'edit', C >;
+ /**
+ * The globally unique identifier for the post.
+ */
+ guid: ContextualField< RenderedText< C >, 'view' | 'edit', C >;
+ /**
+ * Unique identifier for the post.
+ */
+ id: number;
+ /**
+ * URL to the post.
+ */
+ link: string;
+ /**
+ * The date the post was last modified, in the site's timezone.
+ */
+ modified: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * The date the post was last modified, as GMT.
+ */
+ modified_gmt: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * An alphanumeric identifier for the post unique to its type.
+ */
+ slug: string;
+ /**
+ * A named status for the post.
+ */
+ status: ContextualField< PostStatus, 'view' | 'edit', C >;
+ /**
+ * Type of post.
+ */
+ type: string;
+ /**
+ * A password to protect access to the content and excerpt.
+ */
+ password: ContextualField< string, 'edit', C >;
+ /**
+ * Permalink template for the post.
+ */
+ permalink_template: ContextualField< string, 'edit', C >;
+ /**
+ * Slug automatically generated from the post title.
+ */
+ generated_slug: ContextualField< string, 'edit', C >;
+ /**
+ * The title for the post.
+ */
+ title: RenderedText< C >;
+ /**
+ * The content for the post.
+ */
+ content: ContextualField<
+ RenderedText< C > & {
+ /**
+ * Whether the content is protected with a password.
+ */
+ is_protected: boolean;
+ /**
+ * Version of the content block format used by the page.
+ */
+ block_version: ContextualField< string, 'edit', C >;
+ },
+ 'view' | 'edit',
+ C
+ >;
+ /**
+ * The ID for the author of the post.
+ */
+ author: number;
+ /**
+ * The excerpt for the post.
+ */
+ excerpt: RenderedText< C > & {
+ protected: boolean;
+ };
+ /**
+ * The ID of the featured media for the post.
+ */
+ featured_media: number;
+ /**
+ * Whether or not comments are open on the post.
+ */
+ comment_status: ContextualField<
+ CommentingStatus,
+ 'view' | 'edit',
+ C
+ >;
+ /**
+ * Whether or not the post can be pinged.
+ */
+ ping_status: ContextualField< PingStatus, 'view' | 'edit', C >;
+ /**
+ * The format for the post.
+ */
+ format: ContextualField< PostFormat, 'view' | 'edit', C >;
+ /**
+ * Meta fields.
+ */
+ meta: ContextualField<
+ Record< string, string >,
+ 'view' | 'edit',
+ C
+ >;
+ /**
+ * Whether or not the post should be treated as sticky.
+ */
+ sticky: ContextualField< boolean, 'view' | 'edit', C >;
+ /**
+ * The theme file to use to display the post.
+ */
+ template: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * The terms assigned to the post in the category taxonomy.
+ */
+ categories: ContextualField< number[], 'view' | 'edit', C >;
+ /**
+ * The terms assigned to the post in the post_tag taxonomy.
+ */
+ tags: ContextualField< number[], 'view' | 'edit', C >;
+ }
+ }
+}
+
+export type Post< C extends Context > = OmitNevers<
+ _BaseEntityTypes.Post< C >
+>;
diff --git a/packages/core-data/src/types/settings.ts b/packages/core-data/src/types/settings.ts
new file mode 100644
index 0000000000000..978ce32e9b416
--- /dev/null
+++ b/packages/core-data/src/types/settings.ts
@@ -0,0 +1,93 @@
+/**
+ * Internal dependencies
+ */
+import { CommentingStatus, Context, OmitNevers, PingStatus } from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface Settings< C extends Context > {
+ /**
+ * What to show on the front page
+ */
+ show_on_front: string;
+ /**
+ * The ID of the page that should be displayed on the front page
+ */
+ page_on_front: number;
+ /**
+ * Site title.
+ */
+ title: string;
+ /**
+ * Site tagline.
+ */
+ description: string;
+ /**
+ * Site URL.
+ */
+ url: string;
+ /**
+ * This address is used for admin purposes, like new user notification.
+ */
+ email: string;
+ /**
+ * A city in the same timezone as you.
+ */
+ timezone: string;
+ /**
+ * A date format for all date strings.
+ */
+ date_format: string;
+ /**
+ * A time format for all time strings.
+ */
+ time_format: string;
+ /**
+ * A day number of the week that the week should start on.
+ */
+ start_of_week: number;
+ /**
+ * WordPress locale code.
+ */
+ language: string;
+ /**
+ * Convert emoticons like :-) and :-P to graphics on display.
+ */
+ use_smilies: boolean;
+ /**
+ * Default post category.
+ */
+ default_category: number;
+ /**
+ * Default post format.
+ */
+ default_post_format: string;
+ /**
+ * Blog pages show at most.
+ */
+ posts_per_page: number;
+ /**
+ * Allow link notifications from other blogs (pingbacks and trackbacks) on new articles.
+ */
+ default_ping_status: PingStatus;
+ /**
+ * Allow people to submit comments on new posts.
+ */
+ default_comment_status: CommentingStatus;
+ /**
+ * Site logo.
+ */
+ site_logo: number;
+ /**
+ * Site icon.
+ */
+ site_icon: number;
+ }
+ }
+}
+
+export type Settings< C extends Context > = OmitNevers<
+ _BaseEntityTypes.Settings< C >
+>;
diff --git a/packages/core-data/src/types/sidebar.ts b/packages/core-data/src/types/sidebar.ts
new file mode 100644
index 0000000000000..7ff4b209ea3ce
--- /dev/null
+++ b/packages/core-data/src/types/sidebar.ts
@@ -0,0 +1,60 @@
+/**
+ * Internal dependencies
+ */
+import { Widget } from './widget';
+import { Context, OmitNevers } from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface Sidebar< C extends Context > {
+ /**
+ * ID of sidebar.
+ */
+ id: string;
+ /**
+ * Unique name identifying the sidebar.
+ */
+ name: string;
+ /**
+ * Description of sidebar.
+ */
+ description: string;
+ /**
+ * Extra CSS class to assign to the sidebar in the Widgets interface.
+ */
+ class: string;
+ /**
+ * HTML content to prepend to each widget's HTML output when assigned to this sidebar. Default is an opening list item element.
+ */
+ before_widget: string;
+ /**
+ * HTML content to append to each widget's HTML output when assigned to this sidebar. Default is a closing list item element.
+ */
+ after_widget: string;
+ /**
+ * HTML content to prepend to the sidebar title when displayed. Default is an opening h2 element.
+ */
+ before_title: string;
+ /**
+ * HTML content to append to the sidebar title when displayed. Default is a closing h2 element.
+ */
+ after_title: string;
+ /**
+ * Status of sidebar.
+ */
+ status: SidebarStatus;
+ /**
+ * Nested widgets.
+ */
+ widgets: ( Widget< C > | string )[];
+ }
+ }
+}
+
+type SidebarStatus = 'active' | 'inactive';
+
+export type Sidebar< C extends Context > = OmitNevers<
+ _BaseEntityTypes.Sidebar< C >
+>;
diff --git a/packages/core-data/src/types/taxonomy.ts b/packages/core-data/src/types/taxonomy.ts
new file mode 100644
index 0000000000000..120831dbd7acf
--- /dev/null
+++ b/packages/core-data/src/types/taxonomy.ts
@@ -0,0 +1,92 @@
+/**
+ * Internal dependencies
+ */
+import { Context, ContextualField, OmitNevers } from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface Taxonomy< C extends Context > {
+ /**
+ * All capabilities used by the taxonomy.
+ */
+ capabilities: ContextualField<
+ Record< string, string >,
+ 'edit',
+ C
+ >;
+ /**
+ * A human-readable description of the taxonomy.
+ */
+ description: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * Whether or not the taxonomy should have children.
+ */
+ hierarchical: ContextualField< boolean, 'view' | 'edit', C >;
+ /**
+ * Human-readable labels for the taxonomy for various contexts.
+ */
+ labels: ContextualField< Record< string, string >, 'edit', C >;
+ /**
+ * The title for the taxonomy.
+ */
+ name: string;
+ /**
+ * An alphanumeric identifier for the taxonomy.
+ */
+ slug: string;
+ /**
+ * Whether or not the term cloud should be displayed.
+ */
+ show_cloud: ContextualField< boolean, 'edit', C >;
+ /**
+ * Types associated with the taxonomy.
+ */
+ types: ContextualField< string[], 'view' | 'edit', C >;
+ /**
+ * REST base route for the taxonomy.
+ */
+ rest_base: string;
+ /**
+ * REST namespace route for the taxonomy.
+ */
+ rest_namespace: string;
+ /**
+ * The visibility settings for the taxonomy.
+ */
+ visibility: TaxonomyVisibility;
+ }
+
+ export interface TaxonomyVisibility {
+ /**
+ * Whether a taxonomy is intended for use publicly either via the admin interface or by front-end users.
+ */
+ public: boolean;
+ /**
+ * Whether the taxonomy is publicly queryable.
+ */
+ publicly_queryable: boolean;
+ /**
+ * Whether to generate a default UI for managing this taxonomy.
+ */
+ show_ui: boolean;
+ /**
+ * Whether to allow automatic creation of taxonomy columns on associated post-types table.
+ */
+ show_admin_column: boolean;
+ /**
+ * Whether to make the taxonomy available for selection in navigation menus.
+ */
+ show_in_nav_menus: boolean;
+ /**
+ * Whether to show the taxonomy in the quick/bulk edit panel.
+ */
+ show_in_quick_edit: boolean;
+ }
+ }
+}
+
+export type Taxonomy< C extends Context > = OmitNevers<
+ _BaseEntityTypes.Taxonomy< C >
+>;
diff --git a/packages/core-data/src/types/theme.ts b/packages/core-data/src/types/theme.ts
new file mode 100644
index 0000000000000..d3e58fb994861
--- /dev/null
+++ b/packages/core-data/src/types/theme.ts
@@ -0,0 +1,222 @@
+/**
+ * Internal dependencies
+ */
+import { Context, PostFormat, RenderedText, OmitNevers } from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface Theme< C extends Context > {
+ /**
+ * The theme's stylesheet. This uniquely identifies the theme.
+ */
+ stylesheet: string;
+ /**
+ * The theme's template. If this is a child theme, this refers to the parent theme, otherwise this is the same as the theme's stylesheet.
+ */
+ template: string;
+ /**
+ * The theme author.
+ */
+ author: RenderedText< 'edit' >;
+ /**
+ * The website of the theme author.
+ */
+ author_uri: RenderedText< 'edit' >;
+ /**
+ * A description of the theme.
+ */
+ description: RenderedText< 'edit' >;
+ /**
+ * The name of the theme.
+ */
+ name: RenderedText< 'edit' >;
+ /**
+ * The minimum PHP version required for the theme to work.
+ */
+ requires_php: string;
+ /**
+ * The minimum WordPress version required for the theme to work.
+ */
+ requires_wp: string;
+ /**
+ * The theme's screenshot URL.
+ */
+ screenshot: string;
+ /**
+ * Tags indicating styles and features of the theme.
+ */
+ tags: RenderedText< 'edit' >;
+ /**
+ * The theme's text domain.
+ */
+ textdomain: string;
+ /**
+ * Features supported by this theme.
+ */
+ theme_supports: ThemeSupports;
+ /**
+ * The URI of the theme's webpage.
+ */
+ theme_uri: RenderedText< 'edit' >;
+ /**
+ * The theme's current version.
+ */
+ version: string;
+ /**
+ * A named status for the theme.
+ */
+ status: ThemeStatus;
+ }
+
+ export type ThemeStatus = 'active' | 'inactive';
+
+ export interface ThemeSupports {
+ /**
+ * Whether theme opts in to wide alignment CSS class.
+ */
+ 'align-wide': boolean;
+ /**
+ * Whether posts and comments RSS feed links are added to head.
+ */
+ 'automatic-feed-links': boolean;
+ /**
+ * Custom background if defined by the theme.
+ */
+ 'custom-background': boolean | CustomBackground;
+ /**
+ * Custom header if defined by the theme.
+ */
+ 'custom-header': boolean | CustomHeader;
+ /**
+ * Custom logo if defined by the theme.
+ */
+ 'custom-logo': boolean | CustomLogo;
+ /**
+ * Whether the theme enables Selective Refresh for Widgets being managed with the Customizer.
+ */
+ 'customize-selective-refresh-widgets': boolean;
+ /**
+ * Whether theme opts in to the dark editor style UI.
+ */
+ 'dark-editor-style': boolean;
+ /**
+ * Whether the theme disables custom colors.
+ */
+ 'disable-custom-colors': boolean;
+ /**
+ * Whether the theme disables custom font sizes.
+ */
+ 'disable-custom-font-sizes': boolean;
+ /**
+ * Whether the theme disables custom gradients.
+ */
+ 'disable-custom-gradients': boolean;
+ /**
+ * Custom color palette if defined by the theme.
+ */
+ 'editor-color-palette': boolean | Color[];
+ /**
+ * Custom font sizes if defined by the theme.
+ */
+ 'editor-font-sizes': boolean | FontSize[];
+ /**
+ * Custom gradient presets if defined by the theme.
+ */
+ 'editor-gradient-presets': boolean | GradientPreset[];
+ /**
+ * Whether theme opts in to the editor styles CSS wrapper.
+ */
+ 'editor-styles': boolean;
+ /**
+ * Allows use of HTML5 markup for search forms, comment forms, comment lists, gallery, and caption.
+ */
+ html5: boolean | Html5Option[];
+ /**
+ * Post formats supported.
+ */
+ formats: PostFormat[];
+ /**
+ * The post types that support thumbnails or true if all post types are supported.
+ */
+ 'post-thumbnails': boolean | string[];
+ /**
+ * Whether the theme supports responsive embedded content.
+ */
+ 'responsive-embeds': boolean;
+ /**
+ * Whether the theme can manage the document title tag.
+ */
+ 'title-tag': boolean;
+ /**
+ * Whether theme opts in to default WordPress block styles for viewing.
+ */
+ 'wp-block-styles': boolean;
+ }
+
+ export interface CustomBackground {
+ 'default-image': string;
+ 'default-preset': 'default' | 'fill' | 'fit' | 'repeat' | 'custom';
+ 'default-position-x': 'left' | 'center' | 'right';
+ 'default-position-y': 'left' | 'center' | 'right';
+ 'default-size': 'auto' | 'contain' | 'cover';
+ 'default-repeat': 'repeat-x' | 'repeat-y' | 'repeat' | 'no-repeat';
+ 'default-attachment': 'scroll' | 'fixed';
+ 'default-color': string;
+ }
+
+ export interface CustomHeader {
+ 'default-image': string;
+ 'random-default': boolean;
+ width: number;
+ height: number;
+ 'flex-height': boolean;
+ 'flex-width': boolean;
+ 'default-text-color': string;
+ 'header-text': boolean;
+ uploads: boolean;
+ video: boolean;
+ }
+
+ export interface CustomLogo {
+ width: number;
+ height: number;
+ 'flex-width': boolean;
+ 'flex-height': boolean;
+ 'header-text': string[];
+ 'unlink-homepage-logo': boolean;
+ }
+
+ export interface Color {
+ name: string;
+ slug: string;
+ color: string;
+ }
+
+ export interface FontSize {
+ name: string;
+ size: number;
+ slug: string;
+ }
+
+ export interface GradientPreset {
+ name: string;
+ gradient: string;
+ slug: string;
+ }
+
+ export type Html5Option =
+ | 'search-form'
+ | 'comment-form'
+ | 'comment-list'
+ | 'gallery'
+ | 'caption'
+ | 'script'
+ | 'style';
+ }
+}
+
+export type Theme< C extends Context > = OmitNevers<
+ _BaseEntityTypes.Theme< C >
+>;
diff --git a/packages/core-data/src/types/type.ts b/packages/core-data/src/types/type.ts
new file mode 100644
index 0000000000000..2841559eb1139
--- /dev/null
+++ b/packages/core-data/src/types/type.ts
@@ -0,0 +1,80 @@
+/**
+ * Internal dependencies
+ */
+import { Context, ContextualField, OmitNevers } from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface Type< C extends Context > {
+ /**
+ * All capabilities used by the post type.
+ */
+ capabilities: ContextualField<
+ Record< string, string >,
+ 'edit',
+ C
+ >;
+ /**
+ * A human-readable description of the post type.
+ */
+ description: ContextualField< string, 'view' | 'edit', C >;
+ /**
+ * Whether or not the post type should have children.
+ */
+ hierarchical: ContextualField< boolean, 'view' | 'edit', C >;
+ /**
+ * Whether or not the post type can be viewed.
+ */
+ viewable: ContextualField< boolean, 'edit', C >;
+ /**
+ * Human-readable labels for the post type for various contexts.
+ */
+ labels: ContextualField< Record< string, string >, 'edit', C >;
+ /**
+ * The title for the post type.
+ */
+ name: string;
+ /**
+ * An alphanumeric identifier for the post type.
+ */
+ slug: string;
+ /**
+ * All features, supported by the post type.
+ */
+ supports: ContextualField< Record< string, string >, 'edit', C >;
+ /**
+ * Taxonomies associated with post type.
+ */
+ taxonomies: ContextualField< string[], 'view' | 'edit', C >;
+ /**
+ * REST base route for the post type.
+ */
+ rest_base: string;
+ /**
+ * REST route's namespace for the post type.
+ */
+ rest_namespace: string;
+ /**
+ * The visibility settings for the post type.
+ */
+ visibility: ContextualField< TypeVisibility, 'edit', C >;
+ }
+
+ interface TypeVisibility {
+ /**
+ * Whether to generate a default UI for managing this post type.
+ */
+ show_ui: boolean;
+ /**
+ * Whether to make the post type is available for selection in navigation menus.
+ */
+ show_in_nav_menus: boolean;
+ }
+ }
+}
+
+export type Type< C extends Context > = OmitNevers<
+ _BaseEntityTypes.Type< C >
+>;
diff --git a/packages/core-data/src/types/user.ts b/packages/core-data/src/types/user.ts
new file mode 100644
index 0000000000000..172d369b44bbb
--- /dev/null
+++ b/packages/core-data/src/types/user.ts
@@ -0,0 +1,109 @@
+/**
+ * Internal dependencies
+ */
+import { AvatarUrls, Context, ContextualField, OmitNevers } from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface User< C extends Context > {
+ /**
+ * Unique identifier for the user.
+ */
+ id: number;
+ /**
+ * Login name for the user.
+ */
+ username: ContextualField< string, 'edit', C >;
+ /**
+ * Display name for the user.
+ */
+ name: string;
+ /**
+ * First name for the user.
+ */
+ first_name: ContextualField< string, 'edit', C >;
+ /**
+ * Last name for the user.
+ */
+ last_name: ContextualField< string, 'edit', C >;
+ /**
+ * The email address for the user.
+ */
+ email: ContextualField< string, 'edit', C >;
+ /**
+ * URL of the user.
+ */
+ url: string;
+ /**
+ * Description of the user.
+ */
+ description: string;
+ /**
+ * Author URL of the user.
+ */
+ link: string;
+ /**
+ * Locale for the user.
+ */
+ locale: ContextualField< string, 'edit', C >;
+ /**
+ * The nickname for the user.
+ */
+ nickname: ContextualField< string, 'edit', C >;
+ /**
+ * An alphanumeric identifier for the user.
+ */
+ slug: string;
+ /**
+ * Registration date for the user.
+ */
+ registered_date: ContextualField< string, 'edit', C >;
+ /**
+ * Roles assigned to the user.
+ */
+ roles: ContextualField< string[], 'edit', C >;
+ /**
+ * Password for the user.
+ *
+ * This is never sent from the server to the client
+ * but exists because we might send an update to the
+ * server with a new password to set.
+ */
+ password?: string;
+ /**
+ * All capabilities assigned to the user.
+ */
+ capabilities: ContextualField<
+ Record< string, string >,
+ 'edit',
+ C
+ >;
+ /**
+ * Any extra capabilities assigned to the user.
+ */
+ extra_capabilities: ContextualField<
+ Record< string, string >,
+ 'edit',
+ C
+ >;
+ /**
+ * Avatar URLs for the user.
+ */
+ avatar_urls: AvatarUrls;
+ /**
+ * Meta fields.
+ */
+ meta: ContextualField<
+ Record< string, string >,
+ 'view' | 'edit',
+ C
+ >;
+ }
+ }
+}
+
+export type User< C extends Context > = OmitNevers<
+ _BaseEntityTypes.User< C >
+>;
diff --git a/packages/core-data/src/types/widget-type.ts b/packages/core-data/src/types/widget-type.ts
new file mode 100644
index 0000000000000..82f65ea493141
--- /dev/null
+++ b/packages/core-data/src/types/widget-type.ts
@@ -0,0 +1,37 @@
+/**
+ * Internal dependencies
+ */
+import { Context, OmitNevers } from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface WidgetType< C extends Context > {
+ /**
+ * Unique slug identifying the widget type.
+ */
+ id: string;
+ /**
+ * Human-readable name identifying the widget type.
+ */
+ name: string;
+ /**
+ * Description of the widget.
+ */
+ description: string;
+ /**
+ * Whether the widget supports multiple instances
+ */
+ is_multi: boolean;
+ /**
+ * Class name
+ */
+ classname: string;
+ }
+ }
+}
+
+export type WidgetType< C extends Context > = OmitNevers<
+ _BaseEntityTypes.WidgetType< C >
+>;
diff --git a/packages/core-data/src/types/widget.ts b/packages/core-data/src/types/widget.ts
new file mode 100644
index 0000000000000..f1b5a489e9297
--- /dev/null
+++ b/packages/core-data/src/types/widget.ts
@@ -0,0 +1,64 @@
+/**
+ * Internal dependencies
+ */
+import { Context, ContextualField, OmitNevers } from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface Widget< C extends Context > {
+ /**
+ * Unique identifier for the widget.
+ */
+ id: string;
+ /**
+ * The type of the widget. Corresponds to ID in widget-types endpoint.
+ */
+ id_base: string;
+ /**
+ * The sidebar the widget belongs to.
+ */
+ sidebar: string;
+ /**
+ * HTML representation of the widget.
+ */
+ rendered: string;
+ /**
+ * HTML representation of the widget admin form.
+ */
+ rendered_form: ContextualField< string, 'edit', C >;
+ /**
+ * Instance settings of the widget, if supported.
+ */
+ instance: ContextualField< WidgetInstance, 'edit', C >;
+ /**
+ * URL-encoded form data from the widget admin form. Used
+ * to update a widget that does not support instance.
+ *
+ * This is never sent from the server to the client but exists
+ * because we might send an update.
+ */
+ form_data?: string;
+ }
+
+ interface WidgetInstance {
+ /**
+ * Base64 encoded representation of the instance settings.
+ */
+ encoded: string;
+ /**
+ * Cryptographic hash of the instance settings.
+ */
+ hash: string;
+ /**
+ * Unencoded instance settings, if supported.
+ */
+ raw: Record< string, string >;
+ }
+ }
+}
+
+export type Widget< C extends Context > = OmitNevers<
+ _BaseEntityTypes.Widget< C >
+>;
diff --git a/packages/core-data/src/types/wp-template-part.ts b/packages/core-data/src/types/wp-template-part.ts
new file mode 100644
index 0000000000000..36fc050900338
--- /dev/null
+++ b/packages/core-data/src/types/wp-template-part.ts
@@ -0,0 +1,94 @@
+/**
+ * Internal dependencies
+ */
+import {
+ Context,
+ PostStatus,
+ RenderedText,
+ OmitNevers,
+ ContextualField,
+} from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface WpTemplatePart< C extends Context > {
+ /**
+ * ID of template.
+ */
+ id: string;
+ /**
+ * Unique slug identifying the template.
+ */
+ slug: string;
+ /**
+ * Theme identifier for the template.
+ */
+ theme: string;
+ /**
+ * Type of template.
+ */
+ type: string;
+ /**
+ * Source of template
+ */
+ source: string;
+ /**
+ * Source of a customized template
+ */
+ origin: string;
+ /**
+ * Content of template.
+ *
+ * This field never has a `rendered` property when reading but still uses
+ * the RenderedText type so it can be set as a string when sending updates to
+ * the server.
+ *
+ * TODO: Figure out how to mesh this with `RenderedText`
+ */
+ content: ContextualField<
+ RenderedText< C > & {
+ /**
+ * Version of the content block format used by the template.
+ */
+ block_version: ContextualField< number, 'edit', C >;
+ },
+ 'view' | 'edit',
+ C
+ >;
+ /**
+ * Title of template.
+ */
+ title: RenderedText< 'edit' >;
+ /**
+ * Description of template.
+ */
+ description: string;
+ /**
+ * Status of template.
+ */
+ status: PostStatus;
+ /**
+ * Post ID.
+ */
+ wp_id: number;
+ /**
+ * Theme file exists.
+ */
+ has_theme_file: Record< string, string >;
+ /**
+ * The ID for the author of the template.
+ */
+ author: number;
+ /**
+ * Where the template part is intended for use (header, footer, etc.)
+ */
+ area: string;
+ }
+ }
+}
+
+export type WpTemplatePart< C extends Context > = OmitNevers<
+ _BaseEntityTypes.WpTemplatePart< C >
+>;
diff --git a/packages/core-data/src/types/wp-template.ts b/packages/core-data/src/types/wp-template.ts
new file mode 100644
index 0000000000000..33fa31787792a
--- /dev/null
+++ b/packages/core-data/src/types/wp-template.ts
@@ -0,0 +1,94 @@
+/**
+ * Internal dependencies
+ */
+import {
+ Context,
+ PostStatus,
+ RenderedText,
+ OmitNevers,
+ ContextualField,
+} from './helpers';
+
+import { BaseEntityTypes as _BaseEntityTypes } from './base-entity-types';
+
+declare module './base-entity-types' {
+ export namespace BaseEntityTypes {
+ export interface WpTemplate< C extends Context > {
+ /**
+ * ID of template.
+ */
+ id: string;
+ /**
+ * Unique slug identifying the template.
+ */
+ slug: string;
+ /**
+ * Theme identifier for the template.
+ */
+ theme: string;
+ /**
+ * Type of template.
+ */
+ type: string;
+ /**
+ * Source of template
+ */
+ source: string;
+ /**
+ * Source of a customized template
+ */
+ origin: string;
+ /**
+ * Content of template.
+ *
+ * This field never has a `rendered` property when reading but still uses
+ * the RenderedText type so it can be set as a string when sending updates to
+ * the server.
+ *
+ * TODO: Figure out how to mesh this with `RenderedText`
+ */
+ content: ContextualField<
+ RenderedText< C > & {
+ /**
+ * Version of the content block format used by the template.
+ */
+ block_version: ContextualField< number, 'edit', C >;
+ },
+ 'view' | 'edit',
+ C
+ >;
+ /**
+ * Title of template.
+ */
+ title: RenderedText< 'edit' >;
+ /**
+ * Description of template.
+ */
+ description: string;
+ /**
+ * Status of template.
+ */
+ status: PostStatus;
+ /**
+ * Post ID.
+ */
+ wp_id: number;
+ /**
+ * Theme file exists.
+ */
+ has_theme_file: Record< string, string >;
+ /**
+ * The ID for the author of the template.
+ */
+ author: number;
+ /**
+ * Whether a template is a custom template.
+ */
+ is_custom: Record< string, string >;
+ }
+ }
+}
+
+export type WpTemplate< C extends Context > = OmitNevers<
+ _BaseEntityTypes.WpTemplate< C >
+>;