我正在尝试使用类型保护来缩小复杂类型的范围。我希望类型保护的错误分支能够理解缩小类型的补充。
interface Model { side: 'left' | 'right'; }
interface LeftModel { side: 'left'; }
interface RightModel { side: 'right'; }
type Either = LeftModel | RightModel;
function isLeft(value: Either): value is LeftModel { // else is RightModel
return value.side === 'left';
}
这似乎是不可能的,至少不是我打算这样做的方式。Typescript 很高兴推断 aEither
可以是模型,但它不接受 aModel
可以是Either
. 这给出了一个错误:
declare const model: Model;
isLeft(model) // ts(2345)
这个问题是根本无法解决的吗?
如果不是,我如何让错误分支缩小到补码?
请参阅此Typescript Playground中的完整示例
编辑
在这个幼稚的例子中,Model
和Either
是等价的,但这可能不能一概而论。我可以通过组合两个类型保护来取得一些进展,以试图通知Model
实际上是有效的类型系统Either
(参见这个新的Playground)。然而,这给我留下了一个不需要的分支(见第 22 行),所以并不完全令人满意。
有没有办法让类型系统知道Either
并Model
严格等价?
我并不特别需要使用类型保护或联合类型,这是我第一次尝试解决问题,但也产生了自己的问题。只有当我们能够保证一个窄化类型的并集和它的相对补集确实等价于窄化类型时,联合类型才是可行的。这依赖于类型系统对补码的理解,但情况可能还不是这样。请参阅此打字稿补充搜索和实用程序类型手册
有人建议使用fp-ts和/或monocle-ts来解决这个问题,但其中一些函数式编程概念仍然让我难以理解。如果有人知道如何在这里应用它们,那会很好。任何一个听起来都可以在这里提供帮助......