[英]Typescript - type guard not narrowing a union with generic types and functions
我有两个使用以下方法的名义类型的函数(抛开为什么我会这样做 - 这个例子被简化以试图让我的问题清楚):
interface OneArgFunc<T> {
label: "oneArgFunc"
innerFunc:(x: string, y:T)=>void
}
interface TwoArgFunc<T> {
label: "twoArgFunc"
innerFunc: (a:number, b:string, c:T)=>void
}
我也有两者的联合和类型守卫来区分:
type UnionFunc<V> = OneArgFunc<V> | TwoArgFunc<V>
// Type guard functions
function isOneArgFunc<V>(func: UnionFunc<V>): func is OneArgFunc<V> {
return func.label === "oneArgFunc"
}
function isTwoArgFunc<V>(func: UnionFunc<V>): func is TwoArgFunc<V> {
return func.label === "twoArgFunc"
}
但是如果我调用联合中的一个类型守卫,它不会将余数(“else”语句)缩小到联合的另一半:
function transfomer<U extends UnionFunc<any>>(func:U){
if(isOneArgFunc(func)) {
return (g:any)=>func.innerFunc("test", g)
}
else {
return (g:any)=>func.innerFunc(1, "test", g)
// ^ -- error here
// TS indicates that narrowed type of innerFunc is
// (property) innerFunc: (arg0: never, arg1: any, c: any) => void
// What is that based on?
}
}
如果我在 else 语句中显式调用第二个类型保护,它会按预期工作:
function transfomerTwo<U extends UnionFunc<any>>(func:U){
if(isOneArgFunc(func)) {
return (y:any)=>func.innerFunc("test", y)
}
else if(isTwoArgFunc(func)) {
return (z:any)=>func.innerFunc(1, "test", z)
}
else {return func}
}
但我不明白为什么上面的第一个不起作用? 由于某种原因,我假设联合并不是真正的二进制,但我无法确切地看到 TS 如何或如何在 else 语句之后为innerFunc 提供奇怪的函数签名。
任何人都可以帮助我理解这一点吗?
完整代码在这个操场上。
以下对你有用吗? 我认为最好将泛型类型指定为 isOneArgFunc。 至少它不再引发任何错误。
function transfomer<T>(func:UnionFunc<T>){
if(isOneArgFunc<T>(func)) {
return (g:any)=>func.innerFunc("test", g)
}
else {
return (g:any)=>func.innerFunc(1, "test", g)
// ^ -- No more error
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.