首页 > 解决方案 > 允许函数接受数组或元组,但强制数组文字在 Flow 中被视为元组

问题描述

我正在为具有getIn函数的库处理流类型。此函数接受一个对象和一个键数组,并返回对象内嵌套位置的值。

现在我用这样的元组很好地输入了它:

declare function getIn<C, K1: $Keys<C>>(
  collection: C,
  keyPath: [K1]
): $ElementType<C, K1>;
declare function getIn<C, K1: $Keys<C>, K2: $Keys<$ElementType<C, K1>>>(
  collection: C,
  keyPath: [K1, K2],
): $ElementType<$ElementType<C, K1>, K2>;
// etc...

当传递的键中存在错误时,这会正确获取嵌套值的正确类型和错误,例如以下示例:

const data = { person: { name: 'Bobbie', friends: [] }};

// string
const correct = getIn(data, ['person', 'name']);

// Cannot call `getIn` because property `name2` (did you mean `name`?) is missing in object literal [1] in index 1. [incompatible-call]
const incorrect = getIn(data, ['person', 'name2']);

但是我想扩展类型以允许一个数组并返回mixed(因为这是一个库,即使我们不知道返回类型,用数组调用它也应该是有效的)。

所以我在该方法中添加了另一个重载:

declare function getIn(
  collection: mixed,
  keyPath: mixed[]
): mixed;

这使得它可以接受数组,但这意味着如果键不正确,传入数组文字时的类型检查不再出错,它只是返回mixed. 这是一个例子:

// This used to error, but now it returns `mixed`.
const incorrect = getIn(data, ['person', 'name2']);

有没有办法做到这一点,如果我传入一个数组文字,它只使用元组重载而不是数组重载?我知道获得一个mixed返回类型总比没有好,但是如果我能够同时获得这两种方法的优点而不是不得不妥协,那就太棒了。

这是上面示例的Flow 尝试

标签: flowtype

解决方案


推荐阅读