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

TypeScript中if语句内类型收窄不生效问题求助

TypeScript类型收窄失效原因解析

你遇到的问题是:在onMessage函数中,明明通过event.name === 'event1'判断了事件类型,但event.data的类型依然是{ id: string; } | { progress: number; },没有被正确收窄为{ id: string; }。

核心代码片段

const events = ['event1', 'event2'] as const

type EventName = (typeof events)[number]

type EventData = {
  event1: {
    id: string
  }
  event2: {
    progress: number
  }
}

type DemoEvent<T extends EventName> = {
  name: T
  data: EventData[T]
}

const createEvent = <TName extends EventName>(name: TName, data: string): DemoEvent<TName> => {
  return {
    name,
    data: JSON.parse(data) as EventData[TName],
  }
}

const isEventName = (name: string): name is EventName => {
  return events.includes(name as EventName)
}

const onMessage = (name: string, data: string) => {
  if (!isEventName(name)) {
    return
  }

  const event = createEvent(name, data)
  if (event.name === 'event1') {
    console.log(event.data) // 此处data类型未被正确收窄
  }
}

问题原因

当你在onMessage里调用createEvent(name, data)时,TypeScript会把name的类型推断为整个EventName联合类型(也就是'event1' | 'event2'),而不是一个具体的字面量类型。这导致event的类型变成了DemoEvent<'event1'> | DemoEvent<'event2'>。

虽然你通过event.name === 'event1'判断了事件名称,但TypeScript目前无法自动将泛型联合类型与属性的字面量判断关联起来完成类型收窄。简单说,TS认不出event.name的具体值和DemoEvent泛型参数之间的绑定关系,所以不会把event.data的类型从联合类型中过滤出来。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 01:36:10