TypeScript直接判断属性存在报错,类型谓词为何能解决?
TypeScript类型收窄:为什么直接判断
page.content报错,类型谓词却能解决? 你定义了联合类型Page = Article | NotFound,在render函数里直接用if (page.content)判断时,TypeScript报错提示content不存在于NotFound类型,但用类型谓词函数isArticle就能正常收窄类型,下面是具体原因解析:
一、为什么直接判断page.content不被TypeScript认可?
TypeScript的类型收窄依赖可被编译器理解的类型守卫逻辑,直接访问page.content存在两个核心问题:
- 联合类型的属性访问限制:
Page是Article和NotFound的联合类型,NotFound类型定义里没有content属性,编译器认为直接访问page.content本身就是不安全的——它无法确定当前page是否为Article类型。 - 结构化类型系统的特性:TypeScript采用结构化类型,
NotFound类型并没有明确禁止包含content属性(比如运行时可能存在{notFound: true, content: ''}这样的对象)。仅仅检查page.content是否存在,编译器无法确认这就能区分Article和NotFound,所以不会自动把类型收窄到Article。
二、类型谓词(page is Article)的作用
你定义的isArticle函数是用户自定义类型守卫,其中page is Article是类型谓词,它的核心作用是:
- 明确向TypeScript声明:当这个函数返回
true时,传入的page参数的类型就是Article。 - 编译器会信任这个断言,在
if (isArticle(page))的代码块内,自动把page的类型从Page收窄到Article,此时访问page.content完全符合类型定义,不会再报错。
函数内部的(page as Article).content是临时类型断言,仅用于在运行时检查content属性是否存在,避免编译阶段的临时报错,而真正让编译器认可这个检查逻辑的是类型谓词本身。
错误示例代码
type Article = { frontMatter: Record<string, unknown>; content: string; } type NotFound = { notFound: true; } type Page = Article | NotFound; function render(page: Page) { if (page.content) { // TypeScript报错 return page.content; // TypeScript报错 } return '404 — not found'; }
修复后的代码(类型谓词)
type Article = { frontMatter: Record<string, unknown>; content: string; } type NotFound = { notFound: true; } type Page = Article | NotFound; function isArticle(page: Page): page is Article { return typeof (page as Article).content !== 'undefined'; } function render(page: Page) { if (isArticle(page)) { return page.content; // 类型已收窄为Article,无报错 } return '404 — not found'; }
内容的提问来源于stack exchange,提问作者h_a
相关产品推荐
相关产品推荐

