Project starts on 18-05-2025
This package provides strongly typed PayloadCMS types, enhancing the type safety and validation of your PayloadCMS queries and operations. It allows you to perform type-safe selections, where clauses, sort operations, and CRUD operations with strong type inference.
Give me a ⭐ if you like it.
PayloadCMS is a great headless CMS, but its default types can be enhanced to provide better type safety and validation. This package supercharges PayloadCMS with:
- Strong type inference for nested queries
- Type-safe field selections
- Enhanced type safety for CRUD operations
IMHO, Payload claims to be type-safe, but not strong as I expected (ton of any...) Give me a ⭐ if you agree :p
- ✨ Type Safety Selection: Type-safe selecting up to any specified depth, not more
string | {collection-object}at the same time. - 🎯 Where Clause Type Safety: Enhanced type checking for query filters
- 📊 Sort Type Safety: Type-safe sorting operations with dot notation support
- 🚀 CRUD Operation Type Safety: Support the following operations:
findfindByIDcreateupdate(byID and Bulk)delete(byID and Bulk)
- 🔍 Type-Safe Types: Support the following type:
AccessResultAccessFilterOptionsFuncFilterOptionsSortWhere
Caution
ALL operations under TypedPayload are rootless by default, meaning overrideAccess = false.
Note
If you want to use root access by default, you can set overrideAccess = true in the constructor of TypedPayload class. eg. const typedPayload = new TypedPayload(payload, { overrideAccess: true });
- PayloadCMS >= 3.0.0
- TypeScript >= 5.0.0
Install the package using npm:
npm install payloadcms-typing-superchargeThen you can use the CLI to generate types.
Tip
Read CLI for more information on using the command line interface.
-
First, import the
TypedPayloadclass:import { TypedPayload } from 'payloadcms-typing-supercharge';
-
Create a type-safe PayloadCMS instance:
const typedPayload = TypedPayload.createTypedPayload(payload);
-
Enjoy type-safe operations! Here are some examples:
interface Profile { // Sample Collection Type
id: string;
name: string;
subProfile: Profile;
}
interface User { // Sample Collection Type
id: string;
name: string;
profile: Profile;
}
const result = await typedPayload.find({
collection: 'users',
depth: 2,
});
result.profile // ✅ Type: Profile, current depth 0
result.profile.subProfile // ✅ Type: Profile, current depth 1
result.profile.subProfile.subProfile // ✅ Type: string (ID), current depth 2
result.profile.subProfile.subProfile.subProfile // ❌ Invalid, depth exceeded, current depth 3interface Profile { // Sample Collection Type
id: string;
name: string;
subProfile: Profile;
}
interface User { // Sample Collection Type
id: string;
name: string;
profile: Profile;
}
await typedPayload.find({
collection: 'users',
where: {
"profile.subProfile.name": { // ✅ Valid selection
equals: 'John Doe'
}
},
});
await typedPayload.find({
collection: 'users',
where: {
"profile.subProfile.firstName": { // ❌ Invalid selection, `firstName` does not exist
equals: 'John Doe'
}
},
});interface Profile { // Sample Collection Type
id: string;
name: string;
subProfile: Profile;
}
interface User { // Sample Collection Type
id: string;
name: string;
profile: Profile;
}
await typedPayload.find({
collection: 'users',
sort: ['name', '-profile.subProfile.name'], // ✅ Valid sort
});
await typedPayload.find({
collection: 'users',
sort: [
'+name', // ❌ Invalid sortting operator, `+` is not allowed
'-profile.subProfile.firstName' // ❌ Invalid sort, `firstName` does not exist
],
});import { createTypedCollectionConfig } from './__generated__/payloadcms-typing-supercharge';
export const Users = createTypedCollectionConfig({
slug: 'users',
fields: [
{
name: 'name',
type: 'text',
},
{
name: 'profile',
type: 'relationship',
relationTo: 'profiles',
},
],
access: { // ✅ Typed
//...
},
});Note
Not all values in the createTypedCollectionConfig are type-safe right now.
--in <path>: The path of yourpayload-types.ts. Default:./src/payload-types.ts.--out <dir>: Output directory to write types. Default:./src/__generated__/payloadcms-typing-supercharge.--depth <n>: Max depth to emit (inclusive from 0..n). Default:6.
Examples:
payloadcms-typing-supercharge --in ./src/payload-types.ts --out ./src/__generated__/payloadcms-typing-supercharge --depth 2n/a
- Optimise typed
Whereperformance - Retype the WHOLE Payload
CollectionConfig
- n/a
Contributions are welcome! If you find a bug or have a feature request, please open an issue. If you want to contribute code, please fork the repository and submit a pull request.
Note
Due to the typing loss in the TypedPayload class after build process, the package will serve as the orginal typescript source code.
Note
TypeScript aliases are not allowed in this project to prevent aliases mapping problem after file copy. So make sure to use the relative path for file imports.
This project is licensed under the MIT License - see the LICENSE file for details
Love it? Consider a donation to support my work.
