How to type new prismic SliceZone components

I just upgrades to prismic/client v6 and prismic/react v2. I also installed prismic/next and prismic/types.

I wanted to replace the next/slicezone with the new slicezone. But I ran into TypeScript problems. All my slice components are typed like this:

interface Props {
  slice: {
    ... all the slice fields
  }
}

export const MySliceComponent: React.FC<Props> = ({ slice }): JSX.Element => {

  return (
    ...
  )
}

But the new SliceZone expects my components to be of type SliceComponentType<SliceLike<string>unknown>'

How do you suggest to type slice components?

Hi @marco3,

Here is an example of how to create your slice with TypeScript.

Please let me know if you need any further help,
Fares

1 Like

@Fares

I'm getting a similar issue. Where does the slice_type field come from? I can't seem to get it in the Prismic graphQL editor.

This is what I see in VSCode

And if I use ! to bypass the null issue I get this, complaining about missing slice_type

Hi @jorundur,

It seems that you are trying to assign the wrong types, because you are using an optional Maybe variable to a SliceZoneLike<SliceLike<String>> that can return null. You have probably to convert
SliceZoneLike<SliceLike> to an optional.

Please let me know if you need any further help,
Fares

@Fares

Thanks for the reply, I think I still need some help though.

What I don't get is why the slice from the document (the x.body1 in my code) doesn't just work "out of the box".

I.e. this is roughly my process:

The types for the Prismic documents are generated automatically from the graphQL API. This gives me the following types for the documents that are relevant here (body1 is the main thing here as that's the slices array field):

export type MyContentPage = _Document &
  _Linkable & {
    __typename?: 'MyContentPage';
    _linkType: Maybe<Scalars['String']>;
    _meta: Meta;
    body: Maybe<Array<MyContentPageBody>>;
    body1: Maybe<Array<MyContentPageBody1>>;
    editorialContentGroup: Maybe<Array<MyContentPageEditorialContentGroup>>;
    pageLayout: Maybe<Scalars['String']>;
    title: Maybe<Scalars['String']>;
  };

export type MyContentPageBody1 = MyContentPageBody1Interesttable;

export type MyContentPageBody1Interesttable = {
  __typename?: 'MyContentPageBody1Interesttable';
  fields: Maybe<Array<MyContentPageBody1InteresttableFields>>;
  label: Maybe<Scalars['String']>;
  type: Maybe<Scalars['String']>;
};

export type MyContentPageBody1InteresttableFields = {
  __typename?: 'MyContentPageBody1InteresttableFields';
  annual_interest_rate: Maybe<Scalars['Json']>;
  availability: Maybe<Scalars['Json']>;
  bank_account_type: Maybe<Scalars['Json']>;
  indexation: Maybe<Scalars['Json']>;
  interest_payment_frequency: Maybe<Scalars['Json']>;
};

The slices field here is called body1.

These are my main questions:

  • The slices field body1 is of the type Maybe<Array<MyContentPageBody1>> because that's what's automatically generated. How do I get it to the form SliceZoneLike<SliceLike<String>> | undefined? I feel like a slice array of a Prismic document (in our case body1) should be automatically typed like that, but I'm probably misunderstanding something
  • The slices body1 don't contain any field called slice_type but from reading the source code of @prismicio/react and from the second screenshot I sent above I can see that's required. When I was playing around in the Prismic graphQL API UI for my repo this field wasn't available anywhere in the body1 slices field. Where does that field come from?

Just to add to this, my query is something like (I've removed some irrelevant code)

query getContentPage($uId: String!, $lang: String!) {
        myContentPage(uid: $uId, lang: $lang) {
          title
          pageLayout
          body1 {
            __typename
            ... on MyContentPageBody1Interesttable {
              type
              fields {
                bank_account_type
                annual_interest_rate
                interest_payment_frequency
                indexation
                availability
              }
            }
          }
        }
      }      

body1 doesn't contain a slice_type field, nor can I access that field within the ... on MyContentPageBody1Interesttable block.

It needs to and should be there, right?

The problem seems to just be that

  • when using the graphQL API we get type
  • but when using the rest API we get slice_type.

This was posted yesterday: Slice type does not work with @prismicio/react v2 SliceZone Component

This is a strange discrepancy and it would be good to get this fixed asap... It's very confusing

This is what I had to do to make it work, but it's a bit hacky. Typescript doesn't complain anymore

{myContentPage?.body1 && (
  <SliceZone
    slices={myContentPage?.body1.map((slice) => {
      return { ...slice, slice_type: slice.type ?? ''};
    })}
  />
)}

(obviously I need other props as well, I'm just showing the minimum required to fix my initial error)

1 Like

Thanks, @jorundur for pointing this out, and the issue has got opened for this issue and we will let you know in case of any updates.

1 Like

Hi @jorundur,

The issue seems to be fixed in this thread

Please let us know if that fix doesn't work for you,
Fares

1 Like