我有一个处理两种类型参数的函数:string和object。预期有3种不同的对象结构。这最多包含4种可能的类型:
type URL = string;
type Item = {| href: string |};
type ItemList = {| results: Item[] |};
type Params = {| offset?: number, limit?: number |};
所以函数的选项类型是:
type Options = URL | Item | ItemList | Params;
以下是实际功能:
// No properties of "Params" are required
// so if they're all omitted, Params === {}
function request(opts: Options = {}) {
if (typeof opts === 'string') {
return 'opts is an URL';
}
if (typeof opts.href === 'string') {
return 'opts is an item';
}
if (Array.isArray(opts.results)) {
return 'opts is a list of items';
}
// Three of the four types are caught
// we're left with "Params" which may or may not
// have a "offset" and "limit" property.
// Destructuring to undefined values is fine here.
// Still, flow complains about the type not being met.
const { offset, limit } = opts;
return 'opts are parameters';
}
Flow抱怨一些事情:
opts = {}
会引发不兼容错误。由于不需要Params
的属性,不应该将空对象匹配吗?请注意,opts = { offset: undefined }
会清除错误。undefined
不应该是有效值吗?从而解构好吗?总结我的问题:
如何定义接受不同类型对象的类型,其中一个没有必需的属性?
答案 0 :(得分:1)
查看Flowtype - making a sealed empty object以获取第一个问题的答案。
对于你的第二个,答案基本上是Flow不完全支持这种类型的改进。 Disjoint unions是为此用例设计的,但您必须为所有对象添加一个discriminator属性。显然,这将需要对您的代码进行一些重大更改。由你来决定这是否可行。
如果不可行,最好的办法可能只是在此函数中强制转换any
,并确保为返回值提供类型注释。看起来它足够小,人类很容易理解,所以这里的类型检查的好处可能不值得努力。当然这是一个最好留给你的判断电话。