Skip to content

A helper to check if a content relationship's field was queried #330

@angeloashmore

Description

@angeloashmore

Is your feature request related to a problem? Please describe.

Content from a content relationship field's document can be included in a query using the fetchLinks or graphQuery options. Typing those fields with TypeScript is difficult, however, requiring type assertions (as) or manual type parameters (getByUID<...>).

Describe the solution you'd like

A helper function could be provided that checks if a field is included in the query and automatically types the property. We can accomplish this using @prismicio/client's Content namespace.

Something like the following isFilledRelatedData could be used:

import {
  Content,
  FilledContentRelationshipField,
  LinkField,
  isFilled,
} from "@prismicio/client";

type DocumentData<TDocumentType extends Content.AllDocumentTypes["type"]> =
  Extract<Content.AllDocumentTypes, { type: TDocumentType }>["data"];

export function isFilledRelatedData<
  TDocumentType extends Content.AllDocumentTypes["type"],
  TFieldID extends keyof DocumentData<TDocumentType>,
>(
  linkField: LinkField,
  documentType: TDocumentType,
  fieldID: TFieldID,
): linkField is FilledContentRelationshipField & {
  data: {
    [P in keyof DocumentData<TDocumentType> as P extends TFieldID
      ? P
      : never]: DocumentData<TDocumentType>[P];
  };
} {
  return (
    isFilled.contentRelationship(linkField) &&
    linkField.type === documentType &&
    typeof linkField.data === "object" &&
    linkField.data !== null &&
    fieldID in linkField.data
  );
}

isFilledRelatedData()'s name can be misleading since it doesn't actually check if the field is filled. Instead, it checks that the linked field was queried via fetchLinks/graphQuery.

We would probably refocus the helper into something like hasRelationshipField(), which would still require you to check that the field was filled with isFilled().

if (
    hasRelationshipField(item.brand, "brand", "title") &&
    isFilled(item.brand)
) {
    // ...
}

Describe alternatives you've considered

Project-specific runtime checkers can be written using isFilled, but it is cumbersome to write and maintain.

See https://community.prismic.io/t/types-for-content-relationship-in-a-slice/12067/2 for an example.

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions