首页 > 解决方案 > 缩小打字稿中的generec类型

问题描述

typescript v4.4.4 为什么泛型类型在类型保护之后没有缩小?我如何解决它?

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<Data>): G<Exclude<Data, A>> => {
  if (!isA(item)) return item // Item still G<Data> instead of G<B | C>
  throw Error('is A')
}

标签: typescript

解决方案


我认为这是因为 Typescript 无法缩小范围G<Data>。它只知道item是类型G<Data>而不是类型G<A>,但不能断定生成的泛型类型应该是G<B | C>。我最好的猜测是它的类型解析器是一个限制。

作为一种解决方法,您可以为相反的检查创建一个函数:

const isNotA = (item: G<Data>): item is G<Exclude<Data, A>> => item.type !== 'a' // or return !isA(item)

const throwOnA = (item: G<Data>): G<Exclude<Data, A>> => {
  if (isNotA(item)) return item // Item is now G<B | C>
  throw Error('is A')
}

我知道这会带走一些魔力,但这是我能想到的最好的了。


推荐阅读