Closed kb1995 closed 2 years ago
Hi @kb1995,
This happens because the type used your Props
interface is more specific than what <SliceZone>
knows. It looks like doc.data.slices
is not typed to be a SliceZone
that contains a hero
Slice.
As a result, <SliceZone>
only knows that doc.data.slices
contains an array of objects containing at least a slice_zone
property. Your Slice component, however, is asking for more data, such as your primary fields.
In this case, your Slice component's props can only be typed with a "generic" Slice using @prismicio/react
's SliceComponentProps
, like this:
import { SliceComponentProps } from "@prismicio/react";
const Hero = ({ slice }: SliceComponentProps) => {
return <div>Your component</div>;
};
This is not ideal since you no longer have a fully typed slice
prop.
To fully type your Slice components, this is what I recommend you do:
Add a type for your Hero Slice using the SharedSlice
type (or Slice
if you aren't using Prismic's Slice Machine tool). It lets you define its primary and item fields without using extend
.
Repeat this for each of your Slice component files.
import { SharedSliceVariation, KeyTextField, RichTextField, ImageField } from "@prismicio/types";
import { SliceComponentProps } from "@prismicio/react";
export type HeroSlice = SharedSlice<
"hero",
SharedSliceVariation<
"default_slice",
{
eyebrow: KeyTextField,
title: RichTextField,
subtitle: RichTextField,
image: ImageField,
},
never
>
>;
type HeroProps = SliceComponentProps<HeroSlice>;
const Hero = (props: HeroProps) => {
return <div>Test</div>;
};
export default Hero
Note that HeroSlice
is exported from the file.
Where you query for your document, type the document. In this example, I've included a Slice for Hero, Text, and CallToAction, but replace these with your actual Slices.
import { PrismicDocument, SliceZone } from "@prismicio/types";
import Hero, { HeroSlice } from "../slices/Hero";
import Text, { TextSlice } from "../slices/Text";
import CallToAction, { CallToActionSlice } from "../slices/CallToAction";
type PageDocument = PrismicDocument<
"page",
{
body: SliceZone<HeroSlice | TextSlice | CallToActionSlice>,
}
>;
// When you query for your document
const doc = client.getByUID<PageDocument>("page", "home");
// When you use SliceZone, it should be fully typed now
<SliceZone
slices={doc.data.slices}
components={{
hero: Hero,
text: Text,
call_to_action: CallToAction,
}}
/>
I'm assuming you're using something like Next.js where you use @prismicio/client
directly. If you are using a different framework like Gatsby, let me know and I can adjust the response.
Hope that helps! I'm going to close this issue, but please let me know if this doesn't work and I'll try to help. 🙂
Also, we plan to automate this TypeScript type set up process. If you're curious, you can see some experiments here: https://github.com/prismicio/prismic-ts-codegen
prismic-ts-codegen
is not something we recommend using today, but feel free to try it out to get a better understanding of how you can build your own document and Slice types.
@angeloashmore Thanks for the answer!
It looks like it's quite difficult to maintain types manually for slices at the moment and it would make the codebase quite messy. Would you recommend to wait for ts-codegen to be in beta before adding Typescript support to our slices?
Hey,
I encounter another Typescript error, which might be my fault, but I can't figure out why is it happening.
My
pages/index.tsx
I get the following error on the components props
This is what my Hero slice looks like