typescript - Typescript - 类型保护不缩小与泛型类型和函数的联合
问题描述
我有两个名义上使用以下方法的函数(抛开我为什么要这样做——这个例子被简化以试图让我的问题更清楚):
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
}
}
推荐阅读
- html - 分页符中的行跨度
- delphi - 如何使用 Delphi 将 Shift 光标向下发送到另一个程序?
- regex - 在 shell 中提取子字符串的更优雅的方法
- ssl - 我们如何使用 x509certificates 加载证书签名请求?
- webforms - 身份服务器 4 引发重定向 uri 未定义错误
- postgresql - pg_rewind:源和目标集群在同一时间线上
- optimization - 在 Amazon QLDB 中优化时间范围过滤器
- react-native - formik 在后台使用 formData 吗?
- c# - 当对象被序列化/反序列化时,委托/事件中的方法引用会做什么?
- javascript - 子元素未出现在网页中