(property) User.events?: {
relationTo: "events";
value: number | Event;
}[] | null | undefined
I can't figure out why Typescript would return a number.
Because of this I have to add a typeguard in my code.
user.events?.map((event) => {
if (typeof event.value === 'number') {
// uhh, why can it be a number?
} else {
// ... Correct event values
}
});
Would love explore better solutions. All help is appreciated.
Provide your payload config code for events
Yes, here you go:
import { isAdmin } from '@/access/isAdmin'
import { isAdminOrHasEventAccess } from '@/access/isAdminOrHasEventAccess'
import { CollectionConfig } from 'payload/types'
export const Events: CollectionConfig = {
slug: 'events',
admin: {
useAsTitle: 'title',
},
versions: {
maxPerDoc: 100,
drafts: true,
},
access: {
create: isAdmin,
read: isAdminOrHasEventAccess('id'),
update: isAdmin,
delete: isAdmin,
},
fields: [
{
name: 'title',
type: 'text',
required: true,
},
{
name: 'slug',
type: 'text',
unique: true,
required: true,
},
{
name: 'playlists',
label: 'Playlists',
type: 'array',
fields: [
{
name: 'playlist',
type: 'relationship',
relationTo: ['playlists'],
},
],
admin: {
initCollapsed: true,
},
},
],
}
Thank you for looking into it.
So this is a common confusion with relationships. If you were to query your users with
depth=0
, events would come back
as an id, not an event. The type reflects this possibility.
Thank you for the help, I'll def check this out.
This is extremely annoying (only because it seems to require more advanced type narrowing than originally expected), any suggestions for how we should combat this?
Proper type narrowing is the way for now
Yeah works as expected with that in place, although I will admit the type narrowing specifically for this situation seems to be more advanced than usual in order to achieve the expected result.
In the past when I compared a non-object type to an object type I could do something as simple as:
if ('property' in object) return object
and you would receive whatever type that object is, however in this case I had to do something like this to get my expected result:
const isRelation = <T extends { id: string | number }>(value: number | T): value is T => {
return (value as T).id !== undefined;
}
export const resolveRelation = <T extends { id : string | number }>(value: number | T) => {
if (isRelation(value)) return value
}
I don't suppose you may have a theory as to why?
I just found it interesting as the type seemed so simple being either a number or some object interface, yet it required some more advanced type narrowing.
Using typeof number or typeof string tends to be easier in my experience
Star
Discord
online
Get dedicated engineering support directly from the Payload team.