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

TypeScript中if语句判断对象属性时的类型推断异常问题

TypeScript类型收窄的局限:交叉类型场景下的类型匹配问题

先看你的代码场景:

export type IssueProps = {
    type: 'job_warning' | 'job_error' | 'task_warning'
    jobId?: string
}

export type JobIssueProps = IssueProps & {
    type: 'job_warning' | 'job_error'
    jobId: string
}

const sendDeadlineJobErrorAlert = (deadlineIssue: JobIssueProps) => {
    console.log(deadlineIssue)
}

const issue = {} as IssueProps

if (issue.type === 'job_error' && issue.jobId) {
    // TypeScript报错
    sendDeadlineJobErrorAlert(issue)
}

if (issue.type === 'job_error' && issue.jobId) {
    // 无报错
    sendDeadlineJobErrorAlert({...issue, type: issue.type, jobId: issue.jobId})
}

报错信息:

Argument of type 'IssueProps' is not assignable to parameter of type 'JobIssueProps'.
  Type 'IssueProps' is not assignable to type '{ type: "job_warning" | "job_error"; jobId: string; }'.
    Types of property 'type' are incompatible.
      Type '"job_warning" | "job_error" | "task_warning"' is not assignable to type '"job_warning" | "job_error"'.
        Type '"task_warning"' is not assignable to type '"job_warning" | "job_error"'.

为什么第一个if报错,第二个不报错?

这不是你的写法错误,而是TypeScript类型系统在处理交叉类型与原类型的收窄映射时的局限:

  1. 第一个if的问题:
    虽然你通过issue.type === 'job_error'收窄了type的取值范围,又通过issue.jobId确认了该属性存在,但TypeScript无法将IssueProps这个宽泛类型,自动推导为JobIssueProps这个交叉类型。
    原因在于:JobIssueProps是IssueProps与另一个类型的交叉,TS的内置类型守卫(比如属性检查、字面量判断)只能收窄对象的单个属性类型,无法自动将整个对象的类型转换为交叉后的复合类型——它仍然认为issue的基础类型是IssueProps,而这个类型的type仍然包含task_warning的可能(即使你已经通过判断排除了)。

  2. 第二个if的正常逻辑:
    当你创建{...issue, type: issue.type, jobId: issue.jobId}这个新对象时,TypeScript会重新推断这个新对象的类型:

    • type此时已经被收窄为'job_error',符合JobIssueProps的type要求;
    • jobId被确认是存在的字符串,符合必填要求;
      所以这个新对象的类型会被自动推断为完全匹配JobIssueProps,自然不会报错。

解决方案

如果不想创建新对象,可以通过类型断言或者自定义类型守卫来解决:

方案1:类型断言

if (issue.type === 'job_error' && issue.jobId) {
    sendDeadlineJobErrorAlert(issue as JobIssueProps)
}

方案2:自定义类型守卫

function isJobIssueProps(issue: IssueProps): issue is JobIssueProps {
    return (issue.type === 'job_warning' || issue.type === 'job_error') && !!issue.jobId
}

if (isJobIssueProps(issue) && issue.type === 'job_error') {
    sendDeadlineJobErrorAlert(issue)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 01:17:41