在Flow中,使用disjoint union类型,我可以使用type refinement根据某个属性选择性地定位联合的子集 .
如果我想将所有代码放在一个switch语句中,那就太棒了 . 但是,如果我想将代码拆分为函数,我不知道如何将类型细化“编码”为类型声明,以便流程“知道”在这些函数中进行了细化 .
在这里's an example of what I' d喜欢这样做 - 它可以在流动操场here上找到 .
是否有(非手动,非冗余)方式来声明 Thing
的子类型或其他语法,以对类型细化进行编码,以便我可以'pass it on'进入 printThingOfTypeA
函数?
type Thing =
| { type: 'a', a: 1 }
| { type: 'a', a: 2 }
| { type: 'b', b: 3 }
| { type: 'b', b: 4 }
| { type: 'c', c: 5 }
| { type: 'c', c: 6 }
function printThing (thing: Thing): void {
switch (thing.type) {
case 'a': console.log(thing.a); break;
// fails, can't be a c field if type is 'b'
case 'b': console.log(thing.c); break;
// fails, can't be an a field if type is 'c'
case 'c': console.log(thing.a); break;
}
}
printThing({ type: 'a', a: 1 })
// what type do I give thingOfTypeA so that flow refines Thing
// to only the options with type 'a', like in the case 'a': statement?
//
// e.g. Hypothetical syntax: (thingOfTypeA: Thing extends { type: 'a' })
//
function printThingOfTypeA (thingOfTypeA: Thing) {
// this is fine as all have a type
console.log('type: ' + thingOfTypeA.type)
// how can this 'know' that I've passed a thing of type 'a'
// so that it doesn't fail?
console.log('a: ' + thingOfTypeA.a)
}
1 回答
您是否考虑将
Thing
的类型拆分为三个定义?(Try)
这样你的函数可以接受更具体的
ThingA
,而其他代码可以使用更通用的Thing
.或者,如果你可以't break it apart, you can just write a type describing what you need in the function param, but then you can'传递任何
Thing
,因为那个东西可能没有必要的属性:(Try)