#TypeScript: handle generated union type for relationship

10 messages ยท Page 1 of 1 (latest)

slim sparrow
#

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

strange falcon
#

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[];
slim sparrow
strange falcon
#

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

limber kraken
bitter spoke
#

yes you should always manually verify the data for sure

slim sparrow
# strange falcon So one thing you will have to be weary of, what if you get docs back with depth:...

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;
  }
});