如何使用Flow键入通用的重新选择选择器?

时间:2018-08-16 23:14:27

标签: javascript lodash flowtype reselect

我有两种相似但截然不同的结构:

type A = { foo: string, bar: string, specialA: string };
type B = { foo: string, bar: string, specialB: string };

我正在使用reselect here中的类型使用flow-typed创建选择器。我所做的唯一修改是导出OutputSelector类型。

我有三个文件,其用途如下:

generic.js:使用以下模式导出通用选择器:

export const someSelector = selector => createSelector(selector, ...)

a.js:像这样导出特定于type A的选择器:

import { someSelector } from './generic.js';

const aSelector = state => state.a;

export selector = someSelector(aSelector);

b.js:与a.js相同,但对于type B

因此,我的想法是将特定选择器传递给通用选择器,该选择器将选择适当的类型。我在制作它时遇到麻烦,以便在某处使用特定选择器时保留类型信息。因此,某些文件只关心type A,因此它从a.js导入选择器,但是Flow抱怨返回的对象可以具有AB的道具。由于很难准确地找到所有错误的出处,因此我将选择器复制粘贴到a.jsb.js中,并确保在不涉及泛型的情况下它们可以工作。然后,我将一个选择器移到generic.js中,以尝试缩小问题的范围。我有这个:

type Base = { foo: string, bar: string };
type SpecificSelector<T> = OutputSelector<State, mixed, T>;
export const selector = <T: Base, A: $ReadOnlyArray<T>, R: { [string]: $ReadOnlyArray<T> }>(specificSelector: SpecificSelector<A>) =>
  createSelector(
    specificSelector,
    (arr: A): R => groupBy(arr, (o: T): mixed => finding.foo),
  );

lodash的{​​{1}}的定义:

groupBy

我得到的错误:

groupBy<V, T>(
  array: $ReadOnlyArray<T>,
  iteratee?: ?ValueOnlyIteratee<T>,
): { [key: V]: $ReadOnlyArray<T> };

我不明白为什么它们不兼容。如果删除通用参数Error ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ apps/acheron/src/selectors/util/generic.js:70:23 Cannot return groupBy(...) because object type [1] is incompatible with R [2]. apps/acheron/src/selectors/util/generic.js 67│ export const selector = <T: Base, A: $ReadOnlyArray<T>, R: { [string]: $ReadOnlyArray<T> }>(specificSelector: SpecificSelector<A>) => createSelector( 68│ specificSelector, 69│ [2] 70│ (arr: A): R => groupBy(arr, (o: T): mixed => o.foo), 71│ ); 72│ flow-typed/npm/lodash_v4.x.x.js [1] 708│ ): { [key: V]: $ReadOnlyArray<T> }; 并仅返回R返回的值,那么我会遇到另一个问题:

groupBy

新错误:

export const selector1 = <T: Base, A: $ReadOnlyArray<T>>(specificSelector: SpecificSelector<A>) => createSelector(
  specificSelector,

  (arr: A): {[string]: $ReadOnlyArray<T>} => groupBy(arr, (o: T): mixed => o.foo),
);

export const selector2 = <T: Base, A: $ReadOnlyArray<T>>(specificSelector: SpecificSelector<A>) => createSelector(
  [selector1(specificSelector),
  (state: State, props: mixed): ?string => props && props.match && props.match.params && typeof props.match.params.appId === 'string' ? props.match.params.appId : null],

  (arr: {[string]: $ReadOnlyArray<T>}, appId: ?string): ?$ReadOnlyArray<T> =>
    arr && appId && arr[appId]
      ? arr[appId]
      : null,
);

我理解这是因为lodash返回的对象不再是通用参数,类型信息正在丢失,并且Flow无法确保两个对象中都包含相同的键吗?

0 个答案:

没有答案