构建Prismic头部巨型菜单时遇ContentRelationship类型错误求解决
Prismic巨型菜单构建中的ContentRelationshipField类型错误解决方法
问题场景
构建网站头部巨型菜单时,使用Prismic客户端查询header文档数据,在格式化子菜单数据时触发TypeScript类型错误:
Property 'data' does not exist on type 'ContentRelationshipField<"header_submenu">'. Property 'data' does not exist on type 'EmptyLinkField<"Document">'.
原因分析
Prismic的ContentRelationshipField是联合类型,包含两种状态:
- 已关联文档:拥有
data属性,存储关联的文档数据 - 空关联(
EmptyLinkField):没有data属性,表示未关联任何文档
TypeScript会严格校验这种不确定性,直接访问item.submenu.data会触发错误,因为无法保证submenu一定是已填充状态。
解决方法
通过空值检查明确submenu的状态,让TypeScript确认data属性存在后再访问,同时处理空关联的边界情况。
方案1:使用Prismic官方工具函数
导入Prismic的isFilled工具函数,快速判断字段是否已填充:
import { isFilled } from '@prismicio/client'; const formatHeaderData = (data: Simplify<HeaderDocumentData>) => { const { menu, logo } = data; const formattedMenu = menu.length ? menu.map((item) => { // 检查子菜单是否为已填充的关联字段 const submenuData = isFilled.contentRelationship(item.submenu) ? item.submenu.data : null; return { label: item.label, is_link: item.is_link, link: item.link, submenu: submenuData ? { cta_image: submenuData.cta_image, menu: submenuData.menu.map((subMenuItem) => { // 检查子菜单项是否为已填充的关联字段 const itemData = isFilled.contentRelationship(subMenuItem.item) ? subMenuItem.item.data : null; return itemData ? { menu_label: itemData.menu_label, menu: itemData.menu, } : { menu_label: '', menu: [], }; }), } : { cta_image: null, menu: [], }, }; }) : []; return { logo, menu: formattedMenu, }; };
方案2:手动判断字段状态
如果不想依赖工具函数,可以手动判断字段的linkType和data是否存在:
const formatHeaderData = (data: Simplify<HeaderDocumentData>) => { const { menu, logo } = data; const formattedMenu = menu.length ? menu.map((item) => { // 手动判断子菜单是否已填充 const isSubmenuValid = item.submenu?.linkType === 'Document' && item.submenu.data; const submenuData = isSubmenuValid ? item.submenu.data : null; return { label: item.label, is_link: item.is_link, link: item.link, submenu: submenuData ? { cta_image: submenuData.cta_image, menu: submenuData.menu.map((subMenuItem) => { // 手动判断子菜单项是否已填充 const isItemValid = subMenuItem.item?.linkType === 'Document' && subMenuItem.item.data; const itemData = isItemValid ? subMenuItem.item.data : null; return itemData ? { menu_label: itemData.menu_label, menu: itemData.menu, } : { menu_label: '', menu: [], }; }), } : { cta_image: null, menu: [], }, }; }) : []; return { logo, menu: formattedMenu, }; };
效果说明
修改后,TypeScript会识别到我们已经处理了空关联的情况,不再触发类型错误;同时代码也能兼容子菜单未填充的场景,避免运行时出现Cannot read property 'data' of undefined的报错。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

