我有两种相似但不同的结构:
type A = { foo: string, bar: string, specialA: string };
type B = { foo: string, bar: string, specialB: string };
我正在使用
reselect
要创建选择器,请使用
flow-typed
here
. 我所做的唯一修改是导出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
所以我的想法是将一个特定的选择器传递给泛型选择器,泛型选择器将选择适当的类型。在使用特定选择器时,我很难将其设置为保留类型信息。所以有些文件只关心
因此,它从中导入选择器
a、 js
A
或
B
. 由于很难准确地找出这一切的错误所在,我将选择器复制粘贴到
确保它们在没有泛型的情况下工作。然后我把一个选择器移到
试图缩小问题的范围。我有这个:
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
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
只需返回
群比
,我还有一个问题:
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,
);
新错误:
Error ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ apps/acheron/src/selectors/util/generic.js:74:4
Cannot call createSelector with array literal bound to selectors because:
⢠Base [1] is incompatible with T [2] in array element of the indexer property of the return value of index 0.
⢠T [1] is incompatible with Base [2] in array element of the indexer property of the return value of index 0.
[1] 70â (arr: A): {[string]: $ReadOnlyArray<T>} => groupBy(arr, (o: T): mixed => o.foo),
71â );
72â
73â export const selector2 = <T: Base, A: $ReadOnlyArray<T>>(specificSelector: SpecificSelector<A>) => createSelector(
74â [selector1(specificSelector),
75â (state: State, props: mixed): ?string => props && props.match && props.match.params && typeof props.match.params.appId === 'string' ? props.match.params.appId : null],
76â
[2] 77â (arr: {[string]: $ReadOnlyArray<T>}, appId: ?string): ?$ReadOnlyArray<T> =>
78â arr && appId && arr[appId]
我理解这一点,因为lodash返回的对象不再是泛型参数,类型信息正在丢失,Flow无法确保两个对象中包含相同的键?