TypeScript联合类型报错:GetStaticPropsResult不存在props属性
TypeScript联合类型访问报错分析与优化方案
我有以下函数定义:
export async function getPageProps( slug: string, variables: { [key: string]: any; } = {}, appendResourcesToPage: Array<AppendedResource> = [], ): Promise<GetStaticPropsResult<PageProps>> { ... }
对应的接口与类型定义:
export interface PageProps { pageData: any; menus: { headerMenu: MenuItem[]; footerMenu: MenuItem[]; drawerMenu: MenuItem[]; drawerFooterMenu: MenuItem[]; }; siteOptions: SiteOptions; globalSettings: GlobalSettingsQuery | null; } export type GetStaticPropsResult<Props> = | { props: Props; revalidate?: number | boolean } | { redirect: Redirect; revalidate?: number | boolean } | { notFound: true; revalidate?: number | boolean }
当尝试以下写法时出现TypeScript错误:
const commonSiteProps = await getPageProps('', {}, []) as GetStaticPropsResult<PageProps>; const { siteOptions, globalSettings, menus } = commonSiteProps?.props || {};
报错信息:TS2339: Property props does not exist on type GetStaticPropsResult<PageProps>
即使添加类型断言,错误依然存在:
const { siteOptions, globalSettings, menus } = (commonSiteProps as GetStaticPropsResult<PageProps>)?.props || {};
目前已通过以下方式解决,但写法不够简洁,需明确报错原因及更优实现:
const commonSiteProps = await getPageProps('', {}, []); let siteOptions, globalSettings, menus; if (commonSiteProps && 'props' in commonSiteProps) { siteOptions = commonSiteProps?.props.siteOptions; globalSettings = commonSiteProps?.props.globalSettings; menus = commonSiteProps?.props.menus; } if (!siteOptions || !globalSettings || !menus) { throw new Error('Invalid page props.'); }
报错原因
GetStaticPropsResult<PageProps>是联合类型,包含三个分支:
- 带
props属性的成功分支 - 带
redirect属性的重定向分支 - 带
notFound: true的404分支
TypeScript的类型系统会严格校验联合类型的属性访问:只有所有分支都存在的属性,才能直接访问。props仅存在于第一个分支,因此直接访问commonSiteProps.props会触发类型错误。
之前的类型断言无效,是因为断言的对象仍是整个联合类型,并未缩小到具体的带props分支,TypeScript依然无法确定当前值所属分支。
更优解决方案
方案1:类型守卫+解构赋值(简洁版)
利用in操作符做类型守卫,同时完成解构:
const commonSiteProps = await getPageProps('', {}, []); if ('props' in commonSiteProps) { const { siteOptions, globalSettings, menus } = commonSiteProps.props; if (!siteOptions || !globalSettings || !menus) { throw new Error('Invalid page props.'); } // 后续直接使用siteOptions、globalSettings、menus即可 } else { // 处理重定向或404场景,比如抛出错误或执行对应逻辑 throw new Error('Failed to fetch valid page props'); }
方案2:类型断言到具体分支(适用于确定返回成功分支的场景)
如果能确定getPageProps在当前场景下一定返回带props的分支,可直接断言到该具体类型:
const commonSiteProps = await getPageProps('', {}, []) as { props: PageProps; revalidate?: number | boolean }; const { siteOptions, globalSettings, menus } = commonSiteProps.props; if (!siteOptions || !globalSettings || !menus) { throw new Error('Invalid page props.'); }
注意:此方式跳过TypeScript类型检查,仅适合100%确定返回值类型的场景,否则可能引发运行时错误。
方案3:封装工具函数复用判断逻辑
若多处需要处理此类场景,可封装类型守卫工具函数:
function isGetStaticPropsSuccess<Props>( result: GetStaticPropsResult<Props> ): result is { props: Props; revalidate?: number | boolean } { return 'props' in result; } // 使用示例 const commonSiteProps = await getPageProps('', {}, []); if (isGetStaticPropsSuccess(commonSiteProps)) { const { siteOptions, globalSettings, menus } = commonSiteProps.props; if (!siteOptions || !globalSettings || !menus) { throw new Error('Invalid page props.'); } } else { // 处理其他分支逻辑 throw new Error('Failed to fetch valid page props'); }
内容的提问来源于stack exchange,提问作者JorgeeFG
相关产品推荐
相关产品推荐

