๐Ÿ‘€ Our most exciting product launch yet ๐Ÿš€ Join us May 8th for Sanity Connect

Trouble defining TypeScript props on a preview component in Sanity

6 replies
Last updated: Mar 31, 2023
There is not much info on the website on howTo define typescript props on a preview component. Tried creating mine but itโ€™s not working I keep getting errors.


import { defineField, defineType } from 'sanity'
import getYouTubeId from 'get-youtube-id'
import LiteYouTubeEmbed from 'react-lite-youtube-embed'

import 'react-lite-youtube-embed/dist/LiteYouTubeEmbed.css'

type PreviewProps = {
  url: string
  title: string
  renderDefault: any
}

const Preview = ({
  url,
  title = 'YouTube Embed',
  renderDefault
}: PreviewProps) => {
  // const { url, title = 'YouTube Embed', renderDefault } = props

  if (!url) {
    return <div>Missing YouTube URL</div>
  }
  const id = getYouTubeId(url)

  return (
    <div>
      {renderDefault({ title })}
      <LiteYouTubeEmbed title={title} id={id as string} />
    </div>
  )
}

export default defineType({
  name: 'youtube',
  type: 'object',
  title: 'YouTube Embed',
  fields: [
    defineField({
      name: 'title',
      type: 'string',
      title: 'YouTube video title'
    }),
    defineField({
      name: 'url',
      type: 'url',
      title: 'YouTube video URL'
    })
  ],
  preview: {
    select: {
      title: 'title',
      url: 'url'
    }
  },
  components: {
    preview: Preview
  }
})
Mar 31, 2023, 7:57 AM
Hi
user Q
. I've found exploring where Sanity declares and uses types in their node_modules package or in their GitHub repo helps with this. Perhaps in this instance you could try using and expanding on:

import { PreviewProps } from 'sanity'
Mar 31, 2023, 10:06 AM
Tried those but applying it to the props but it still complains about the url etx
Mar 31, 2023, 10:07 AM
Have you tried something like:

PreviewProps & { url: string }
Mar 31, 2023, 10:09 AM
Let me try thank you Oliver i wil let you know
Mar 31, 2023, 10:10 AM
user H


import { PreviewProps, defineField, defineType } from 'sanity'
import getYouTubeId from 'get-youtube-id'
import LiteYouTubeEmbed from 'react-lite-youtube-embed'

import 'react-lite-youtube-embed/dist/LiteYouTubeEmbed.css'

const Preview = (props: PreviewProps & { url: string }) => {
  const { url, title = 'YouTube Embed', renderDefault } = props

  if (!url) {
    return <div>Missing YouTube URL</div>
  }
  const id = getYouTubeId(url)

  return (
    <div>
      {renderDefault({ ...props, title })}
      <LiteYouTubeEmbed title={title as string} id={id as string} />
    </div>
  )
}

export default defineType({
  name: 'youtube',
  type: 'object',
  title: 'YouTube Embed',
  fields: [
    defineField({
      name: 'title',
      type: 'string',
      title: 'YouTube video title'
    }),
    defineField({
      name: 'url',
      type: 'url',
      title: 'YouTube video URL'
    })
  ],
  preview: {
    select: {
      title: 'title',
      url: 'url'
    }
  },
  components: {
    preview: Preview
  }
})
Getting the following error now:


Type '(props: PreviewProps & {    url: string;}) => JSX.Element' is not assignable to type 'ComponentType<PreviewProps<PreviewLayoutKey>> | undefined'.
  Type '(props: PreviewProps & {    url: string;}) => JSX.Element' is not assignable to type 'FunctionComponent<PreviewProps<PreviewLayoutKey>>'.
    Types of parameters 'props' and 'props' are incompatible.
      Type 'PreviewProps<PreviewLayoutKey>' is not assignable to type 'PreviewProps<PreviewLayoutKey> & { url: string; }'.
        Property 'url' is missing in type 'PreviewProps<PreviewLayoutKey>' but required in type '{ url: string; }'.
Mar 31, 2023, 1:34 PM
Hey
user Q
. Not sure why you are getting an error in this case. You could maybe use url as optional:

{ url?: string; }
but perhaps someone with better TS knowledge than myself may be able to help
๐Ÿ˜
Mar 31, 2023, 2:51 PM

Sanityโ€“ build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?