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 } })
关键改动说明
- 泛型类型绑定:用
PreviewProps<YouTubePreviewSelect>明确告诉TypeScript,当前预览组件的props.value包含title和url字段,其中url为必填项 - 从value解构字段:Sanity会自动把
preview.select配置的字段整合到props.value中,直接解构这里的字段可避免类型不匹配 - 移除冗余断言:类型明确后,原代码中
title as string、id as string这类冗余的类型断言可以直接删除
内容的提问来源于stack exchange,提问作者Galanthus
相关产品推荐
相关产品推荐

