A relationship field has the type
string[] | MyCollection[]
which makes sense, as it could change depending on the depth which is used.
Now, how would you best handle the value of this field without too much run-time type checking? I'm using:
let relationshipValue = (
await payload.findByID({
collection: 'sites',
id: docId,
depth: 0,
})
).relationship; // string[] | MyCollection[]
if (relationshipValue.length > 0 && typeof relationshipValue[0] === 'object') {
relationshipValue = relationshipValue.map((doc) => doc.id);
}
relationshipValue = relationshipValue as string[];
However, this feels unsafe and beyond dirty. Any other ideas? Might as well cast it to
any
if I have to use type assertions (as
string[])
in the end
With depth 0 won't it always be string[]? Until we improve our internal typing to account for depth (if possible), I think you would be better off just casting right away
let relationshipValue = (
await payload.findByID({
collection: 'sites',
id: docId,
depth: 0,
})
).relationship as string[];
With depth 0 won't it always be string[]
Hm it would, but doing
as string[]
just feels dirty, it gives me more responsibility to know I can't just change the depth in the future 😅 Was hoping that there is some kind of way to let typescript infer the type, so I don't have to assert the type anymore
So one thing you will have to be weary of, what if you get docs back with depth: 1, but one of the docs was deleted (all that is left is the ID) or you dont have access to one of the docs (you will only get the ID).
So with that in mind, I think the safest thing to do would be to always loop, check the type of the doc when looping and return the id or the doc.id
This is what I did in my project. Hard to reliably get back the Object rather than just the ID so I always type check manually to ensure I got back the right thing.
yes you should always manually verify the data for sure
ah didn't think of that either, that makes it even worse 😅
I guess then this would really be the best/safest:
let relationshipValue = (
await payload.findByID({
collection: 'sites',
id: docId,
depth: 0,
})
).relationship;
currentSummaries = currentSummaries.map((doc) => doc.id ?? doc) as string[];
Although I really hate having to use
as string[]
Or I guess
currentSummaries = currentSummaries.map((doc) => (doc.id as string) ?? (doc as string));
is a bit nicer
Mh found a nicer way!
let relationshipValue = (
await payload.findByID({
collection: 'sites',
id: docId,
depth: 0,
})
).relationship;
relationshipValue = relationshipValue.map((doc: string | MyCollection) => {
if (typeof doc === 'object') {
return doc.id;
} else {
return doc;
}
});
Star
Discord
online
Get help straight from the Payload team with an Enterprise License.