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

TypeScript v4.4.4 类型守卫执行后泛型未收窄如何修复?

问题根因

TypeScript 4.4 版本中,默认不会将非分布式的泛型类型G<A | B | C>自动识别为G<A> | G<B> | G<C>的联合类型,因此你自定义的类型守卫isA只能判断item是否为G<A>,但无法将剩余分支的类型自动收窄为G<B | C>。

修复方案

三种可行的修复方式如下:

方案1:将泛型定义改为分布式条件类型(推荐)

通过分布式条件类型让G<T>在接收联合类型入参时自动拆分为对应联合类型,类型守卫就可以正常执行收窄逻辑:

type Data = A | B | C
// 改造G的定义为分布式条件类型
type G<T extends Data> = T extends unknown ? {
  type: 'a' | 'b'
  data: T
} : never
type A = {
  foo: string
}
type B = {
  bar: string
}
type C = {
  foobar: string
}
const isA = (item: G<Data>): item is G<A> => item.type === 'a'

const throwOnA = (item: G<Data>): G<Exclude<Data, A>> => {
  if (!isA(item)) return item // 此处item会正确收窄为G<B | C>
  throw Error('is A')
}

方案2:显式声明入参为联合类型

如果不想修改原有G<T>的定义,可以直接将函数入参声明为G<A> | G<B> | G<C>的联合类型,也可以触发正常的类型收窄:

type Data = A | B | C
type G<T extends Data> = {
  type: 'a' | 'b'
  data: T
}
type A = {
  foo: string
}
type B = {
  bar: string
}
type C = {
  foobar: string
}
const isA = (item: G<Data>): item is G<A> => item.type === 'a'

// 显式声明入参为联合类型
const throwOnA = (item: G<A> | G<B> | G<C>): G<Exclude<Data, A>> => {
  if (!isA(item)) return item // 类型收窄正常生效
  throw Error('is A')
}

方案3:临时加类型断言(应急方案)

如果不想修改类型定义,也可以在返回处手动添加类型断言跳过类型校验,适合小范围临时修复:

const throwOnA = (item: G<Data>): G<Exclude<Data, A>> => {
  if (!isA(item)) return item as G<Exclude<Data, A>>
  throw Error('is A')
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 01:36:07