Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

TypeScript - Overview

Payload supports TypeScript natively, and not only that, the entirety of the CMS is built with TypeScript. To get started developing with Payload and TypeScript, you can use one of Payload's built-in boilerplates in one line via create-payload-app:

1
npx create-payload-app@latest

Pick a TypeScript project type to get started easily.

Setting up from Scratch

It's also possible to set up a TypeScript project from scratch. We plan to write up a guide for exactly how—so keep an eye out for that, too.

Using Payload's Exported Types

Payload exports a number of types that you may find useful while writing your own custom functionality like Plugins, Hooks, Access Control functions, Custom Views, GraphQL queries / mutations or anything else.

Config Types

Hook Types

Type Helpers

Beyond the concrete interfaces in your generated payload-types.ts (Post, User, etc.), Payload exports a set of generic type helpers from the payload package. Instead of referencing a single collection by name, these resolve dynamically against all of your collections and globals — which makes them especially useful in Plugins, reusable Hooks, and Access Control functions, where the exact collection may not be known ahead of time.

How they resolve

When you run payload generate:types, the generated file augments a global GeneratedTypes interface inside the payload module:

1
// payload-types.ts (generated)
2
declare module 'payload' {
3
export interface GeneratedTypes extends Config {}
4
}

Every helper below is generic over this augmented interface. Because the augmentation lives in your project, the helpers resolve to your actual collections wherever your code is type-checked — including inside a third-party plugin's source once it is installed in your project. If GeneratedTypes has not been augmented (for example, in a plugin's own repository before it is consumed), the helpers gracefully fall back to loose types (string, index signatures) rather than erroring.

Available helpers

Helper

Resolves to

CollectionSlug

A union of all your collection slugs, e.g. `'posts' \

'users' \

'media'`.

DataFromCollectionSlug<TSlug>

The full document type for a collection (the shape returned after read).

RequiredDataFromCollectionSlug<TSlug>

The data shape accepted by create (system fields like id/createdAt become optional).

SelectFromCollectionSlug<TSlug>

The select type for a collection.

TypedCollection

A map of every collection slug to its document type.

GlobalSlug

A union of all your global slugs.

TypedGlobal

A map of every global slug to its data type.

TypedUser

The user type — a union across all auth-enabled collections.

TypedLocale

A union of your configured locale codes (or string if localization is disabled).

DefaultDocumentIDType

Your database's default ID type (string or number).

Example

1
import type {
2
CollectionSlug,
3
DataFromCollectionSlug,
4
CollectionAfterChangeHook,
5
} from 'payload'
6
7
// Constrain a value to any valid collection slug
8
const collections: CollectionSlug[] = ['posts', 'users']
9
10
// Write a hook that stays generic over whichever slug it is attached to
11
function createAuditHook<TSlug extends CollectionSlug>(slug: TSlug) {
12
const hook: CollectionAfterChangeHook<DataFromCollectionSlug<TSlug>> = ({
13
doc,
14
}) => {
15
// `doc` is fully typed to the collection at `slug`
16
return doc
17
}
18
return hook
19
}

Was this page helpful?

Next

Generating TypeScript Interfaces