Block IDs are always nullable
Describe the Bug
Kia ora!
My team is currently using payload 2 as a CMS to support our content editing team across our websites.
However when using payload 2, or 3, block IDs are always nullable in the generated payload-types.ts. This is unexpected, as if a block does exist it should have a unique ID attached to it.
This is resulting in our team having to add unnecessary conditional checks that the ID does exist for a block.
I've tried adding things such as required: true to improve the type of the generated interface, and it does drop the possibility of it being undefined. However the ID then resolves to being string | null, along with surfacing the ID to CMS editors. Adding hidden: true does solve the latter problem.
Ideally ID types become non-nullable, and will always exist for a given block. Is there already advice on how to achieve this, or am I right in thinking this is a bug, and unexpected behaviour?
Link to the code that reproduces this issue
https://github.com/NikoFarrelly/payload-3-id-nullable
Reproduction Steps
pnpx create-payload-app@latest- select 'website' template
- select 'MongoDB' database
- Add a component + config
- in the repro I've added a 'Panel' component + config
- Regenerate types
pnpm generate:types
- Open
payload-types.ts- Find 'Panel' interface
- Interface will look like this
export interface Panel {
richText: {
root: {
type: string;
children: {
type: string;
version: number;
[k: string]: unknown;
}[];
direction: ('ltr' | 'rtl') | null;
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
indent: number;
version: number;
};
[k: string]: unknown;
};
id?: string | null;
blockName?: string | null;
blockType: 'panel';
}
Which area(s) are affected? (Select all that apply)
Not sure
Environment Info
Binaries:
Node: 22.14.0
npm: 10.9.2
Yarn: N/A
pnpm: 9.15.9
Relevant Packages:
payload: 3.31.0
next: 15.2.3
@payloadcms/db-mongodb: 3.31.0
@payloadcms/email-nodemailer: 3.31.0
@payloadcms/graphql: 3.31.0
@payloadcms/live-preview: 3.31.0
@payloadcms/live-preview-react: 3.31.0
@payloadcms/next/utilities: 3.31.0
@payloadcms/payload-cloud: 3.31.0
@payloadcms/plugin-form-builder: 3.31.0
@payloadcms/plugin-nested-docs: 3.31.0
@payloadcms/plugin-redirects: 3.31.0
@payloadcms/plugin-search: 3.31.0
@payloadcms/plugin-seo: 3.31.0
@payloadcms/richtext-lexical: 3.31.0
@payloadcms/translations: 3.31.0
@payloadcms/ui/shared: 3.31.0
react: 19.0.0
react-dom: 19.0.0
Operating System:
Platform: darwin
Arch: x64
Version: Darwin Kernel Version 23.5.0: Wed May 1 20:16:51 PDT 2024; root:xnu-10063.121.3~5/RELEASE_ARM64_T8103
Available memory (MB): 16384
Available CPU cores: 8
Having a similar issue with the nested id's
export const Tests: CollectionConfig = {
slug: 'tests',
admin: {
useAsTitle: 'title',
},
access: access(),
fields: [
{
name: 'id',
type: 'text',
required: true,
},
{
name: 'title',
label: 'Title',
type: 'text',
required: true,
},
{
name: 'questions',
label: 'Questions',
type: 'array',
required: true,
fields: [
{
name: 'id',
type: 'text',
required: true,
defaultValue: crypto.randomUUID(),
},
{
name: 'title',
label: 'Question Title',
type: 'text',
required: true,
},
{
name: 'answers',
label: 'Answers',
type: 'array',
required: true,
fields: [
{
name: 'id',
type: 'text',
required: true,
defaultValue: crypto.randomUUID(),
},
{
name: 'title',
label: 'Answer Title',
type: 'text',
required: true,
},
{
name: 'isCorrect',
label: 'Is Correct',
type: 'checkbox',
defaultValue: false,
},
{
name: 'test-id',
label: 'test-id',
type: 'text',
required: true,
},
],
},
],
},
],
};
In the generated types, the id in the main object has the correct types, but if I have id as an array of fields, in my case test.questions.id or test.questions.answers.id, it has nullable types even if we put the required: true and default values for these fields.
and the same configuration for test-id field generates correct types
It looks like it's a bug only with the fields with a name id somehow.