TypeScript似乎在推断类型保护的并集类型方面存在问题。例如,考虑一个将带有以下签名的类型保护数组组合的函数
function combine<T>(guards: ((x: any) => x is T)[]): (x: any) => x is T
并考虑以下{@ {1}}和A
具有不同属性的类型保护
B
现在,我希望function isA(x: any): x is A
function isB(x: any): x is B
可以工作并且具有推断的类型combine([isA, isB])
,但我收到一条错误消息,指出类型(x: any) => x is A | B
的参数不能分配给类型{{ 1}},这意味着((x: any) => x is A | (x: any) => x is B)[]
被推断为(x: any) => x is A
而不是T
。
明确指定A
时,即A | B
,它可以正常工作。有没有一种方法可以更改T
的签名,以便可以推断出该签名?
答案 0 :(得分:3)
您可以使用类型参数来表示整个函数,而不仅仅是保护类型。这使编译器可以推断保护函数的并集。然后,我们可以使用条件类型来提取受保护类型的并集:
type GuardType<T> = T extends (o: any) => o is infer U ? U : never
class A { q: any }
class B { p: any }
declare function isA(x: any): x is A
declare function isB(x: any): x is B
declare function combine<T extends ((x: any) => x is any)>(guards: T[]): (x: any) => x is GuardType<T>
let isAB = combine([isA, isB]); // (x:any) => x is A|B