sanity-typed icon indicating copy to clipboard operation
sanity-typed copied to clipboard

Nullable Array always projects/arraypostfixes to a null

Open OMikkel opened this issue 1 year ago • 3 comments

Packages:

@sanity-typed/client @sanity-types/types

Issue:

When i am querying for data with groq queries, the generated types does not show hidden fields correct. Hidden fields are permanently null and they do not respect the hidden fields rule set in the schema.

I have been dealing with this issue for 5 hours now and i believe i have tried everything. Any help or insight into why this issue occurs is much appreciated.

Context:

Frontend:

const data = await sanityClient.fetch(`
    *[_type == "footer" && type == "links"]{
        _id,
        title,
        links[]{
            _key,
            title,
            url,
            target
        }
    }
`)

Schema:

export default defineType({
  name: "footer",
  type: "document",
  title: "Footer",
  fields: [
    defineField({
      name: "type",
      type: "string",
      title: "Type",
      options: {
        list: [
          { title: "About", value: "about" },
          { title: "Social", value: "social" },
          { title: "Links", value: "links" },
        ],
      },
      validation: (Rule) => Rule.required(),
    }),
    defineField({
      name: "title",
      type: "string",
      title: "Title",
      validation: (Rule) => Rule.required(),
    }),
   ...,
    defineField({
      name: "links",
      type: "array",
      title: "Links",
      of: [
        defineArrayMember({
          type: "object",
          icon: <LinkIcon />,
          fields: [
            defineField({
              name: "title",
              type: "string",
              title: "Title",
            }),
            defineField({
              name: "url",
              type: "string",
              title: "URL",
            }),
            defineField({
              name: "target",
              type: "string",
              title: "Target",
              options: {
                list: [
                  { title: "Self", value: "_self" },
                  { title: "Blank", value: "_blank" },
                ],
              },
            }),
          ],
          preview: {
            select: {
              title: "title",
              subtitle: "url",
            },
          },
        }),
      ],
      validation: (Rule) =>
        Rule.custom((field, context) => {
          if (context.document?.type === "links" && !field?.length) {
            return "Links are required";
          }
          return true;
        }),
      hidden: ({ document }) => document?.type !== "links",
    }),
    ...,
  ],
});

Real data:

OMikkel avatar Jan 19 '24 20:01 OMikkel

I've made a PR with a test against this in #642, and can confirm that this is indeed a bug. I'll take a look and see.

GROQ will give you a null anywhere you're projecting for something that could be undefined, so links would project to the array's type unioned with a null. My thinking is that the array projection on links (ie links[]) isn't considering that so, when it sees null, it's just failing rather than distributing across the union.

saiichihashimoto avatar Jan 20 '24 20:01 saiichihashimoto

Yeah, I think that's the issue. When I change the projection just to links, it shows the array's type unioned with null but, the moment I change it back to links[], it's just doing a null, which is wrong. I'm guessing this is happening throughout a lot of the codebase honestly.

saiichihashimoto avatar Jan 20 '24 20:01 saiichihashimoto

The other thing to mention is that I don't think it has anything to do with the hidden field. You can see that I've removed it from the test and the issue still persists.

saiichihashimoto avatar Jan 20 '24 21:01 saiichihashimoto