You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sanity预览组件TypeScript类型错误:JSX.Element无法赋值给ComponentType

Sanity YouTube嵌入预览组件TypeScript类型错误解决方案

问题场景

开发Sanity的YouTube嵌入预览组件时,已通过preview.select指定了url字段,但TypeScript仍报错,提示url属性在PreviewProps<PreviewLayoutKey>中缺失,即使尝试用PreviewProps & { url: string }合并类型也无法解决。

错误信息

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; }'.

解决方案

错误根源是没有正确关联Sanity Preview组件的select字段与TypeScript类型。需要通过PreviewProps的泛型参数定义选中字段的类型,而非直接使用交叉类型。

修改后完整代码

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'

// 定义preview.select选中字段的类型
type YouTubePreviewSelect = {
  title?: string;
  url: string;
}

// 通过泛型指定PreviewProps的选中字段类型
const Preview = (props: PreviewProps<YouTubePreviewSelect>) => {
  // 从props.value中解构选中的字段(Sanity会把select结果打包到value里)
  const { title = 'YouTube Embed', url } = props.value;
  const { renderDefault } = props;

  if (!url) {
    return <div>Missing YouTube URL</div>
  }

  const id = getYouTubeId(url);

  return (
    <div>
      {renderDefault({ ...props, title })}
      <LiteYouTubeEmbed title={title} id={id} />
    </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
  }
})

关键改动说明

  1. 泛型类型绑定:用PreviewProps<YouTubePreviewSelect>明确告诉TypeScript,当前预览组件的props.value包含title和url字段,其中url为必填项
  2. 从value解构字段:Sanity会自动把preview.select配置的字段整合到props.value中,直接解构这里的字段可避免类型不匹配
  3. 移除冗余断言:类型明确后,原代码中title as string、id as string这类冗余的类型断言可以直接删除

内容的提问来源于stack exchange,提问作者Galanthus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 11:53:11