在 TypeScript 中使用 createSelector 创建一个选择器工厂
Creating a selector factory with createSelector in TypeScript
像这样创建选择器:
import { createSelector } from 'reselect';
export interface Node {
nodeId: number
nodeName: string
}
export type NodeState = {
nodes: Node[];
text: string;
};
const nodeListState = (state) => state.nodeList;
const byKey = (key: keyof NodeState) => createSelector(
nodeListState, (nodeList: NodeState) => nodeList[key],
);
export const getNodes = byKey('nodes');
export const getText = byKey('text');
在其他地方,使用选择器:
import { useSelector } from 'react-redux';
const nodes = useSelector(selectors.getNodes);
nodes.map(...)
这会导致错误:
Property 'map' does not exist on type 'string | Node[]'.
Property 'map' does not exist on type 'string'. TS2339
变量节点实际上是一个数组。我这样做是不是错了?在 TS 中设置按键创建选择器的函数的正确方法是什么?
这里发生的事情是 typescript 无法区分 byKey('nodes')
和 byKey('text')
。它们 return 是同一类型,即选择文本 string
或节点 Node[]
的选择器。因此 const nodes = useSelector(selectors.getNodes)
return 联合 string | Node[]
并且你得到一个错误 string
不是一个数组。
解决此问题的一种方法是放弃 byKey
并分别创建两个选择器。
但是我们可以使 byKey
正常工作,方法是使它成为一个通用函数,该函数取决于调用它时使用的特定键。这样我们就知道 byKey('nodes')
选择了 'nodes'
属性.
如果您对 nodeListState
应用正确的类型,您实际上不需要将第二个选择器的参数指定为 nodeList: NodeState
,因为它可以根据 return 推断出来第一个选择器的类型。
const nodeListState = (state: {nodeList: NodeState}) => state.nodeList;
const byKey = <K extends keyof NodeState>(key: K) => createSelector(
nodeListState,
(nodeList) => nodeList[key],
);
现在 getNodes
选择 Node[]
,getText
选择 string
。
像这样创建选择器:
import { createSelector } from 'reselect';
export interface Node {
nodeId: number
nodeName: string
}
export type NodeState = {
nodes: Node[];
text: string;
};
const nodeListState = (state) => state.nodeList;
const byKey = (key: keyof NodeState) => createSelector(
nodeListState, (nodeList: NodeState) => nodeList[key],
);
export const getNodes = byKey('nodes');
export const getText = byKey('text');
在其他地方,使用选择器:
import { useSelector } from 'react-redux';
const nodes = useSelector(selectors.getNodes);
nodes.map(...)
这会导致错误:
Property 'map' does not exist on type 'string | Node[]'.
Property 'map' does not exist on type 'string'. TS2339
变量节点实际上是一个数组。我这样做是不是错了?在 TS 中设置按键创建选择器的函数的正确方法是什么?
这里发生的事情是 typescript 无法区分 byKey('nodes')
和 byKey('text')
。它们 return 是同一类型,即选择文本 string
或节点 Node[]
的选择器。因此 const nodes = useSelector(selectors.getNodes)
return 联合 string | Node[]
并且你得到一个错误 string
不是一个数组。
解决此问题的一种方法是放弃 byKey
并分别创建两个选择器。
但是我们可以使 byKey
正常工作,方法是使它成为一个通用函数,该函数取决于调用它时使用的特定键。这样我们就知道 byKey('nodes')
选择了 'nodes'
属性.
如果您对 nodeListState
应用正确的类型,您实际上不需要将第二个选择器的参数指定为 nodeList: NodeState
,因为它可以根据 return 推断出来第一个选择器的类型。
const nodeListState = (state: {nodeList: NodeState}) => state.nodeList;
const byKey = <K extends keyof NodeState>(key: K) => createSelector(
nodeListState,
(nodeList) => nodeList[key],
);
现在 getNodes
选择 Node[]
,getText
选择 string
。