[英]Creating a selector factory with createSelector in TypeScript
Creating selectors like this:像这样创建选择器:
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');
Elsewhere, using the selectors:在其他地方,使用选择器:
import { useSelector } from 'react-redux'; const nodes = useSelector(selectors.getNodes); nodes.map(...)
This results in the error:这会导致错误:
Property 'map' does not exist on type 'string | Node[]'.
Property 'map' does not exist on type 'string'. TS2339
The variable nodes is actually an array.变量节点实际上是一个数组。 Am I going about this all wrong?
我对这一切都错了吗? What's the correct way to set up a function that creates selectors by key in TS?
设置在TS中通过键创建选择器的function的正确方法是什么?
What's happening here is that typescript is not able to distinguish between byKey('nodes')
and byKey('text')
.这里发生的是 typescript 无法区分
byKey('nodes')
和byKey('text')
。 They both return the same type, which is a selector that selects either the text string
or the nodes Node[]
.它们都返回相同的类型,即选择文本
string
或节点Node[]
的选择器。 Thus const nodes = useSelector(selectors.getNodes)
returns the union string | Node[]
因此
const nodes = useSelector(selectors.getNodes)
返回联合string | Node[]
string | Node[]
and you get an error that string
is not an array. string | Node[]
并且您收到一个错误,即string
不是数组。
One way to fix this is to ditch byKey
and create the two selectors separately.解决此问题的一种方法是
byKey
并分别创建两个选择器。
But we can make byKey
work properly by making it a generic function which depends on the specific key that it was called with.但是我们可以通过将
byKey
通用 function 来使其正常工作,这取决于调用它的特定键。 That way we know that byKey('nodes')
selects the 'nodes'
property.这样我们就知道
byKey('nodes')
选择了'nodes'
属性。
If you apply proper typing to nodeListState
, you don't actually need to specify the argument for the second selector as nodeList: NodeState
since it can be inferred based on the return type of the first selector.如果你对
nodeListState
应用正确的类型,你实际上不需要将第二个选择器的参数指定为nodeList: NodeState
因为它可以根据第一个选择器的返回类型来推断。
const nodeListState = (state: {nodeList: NodeState}) => state.nodeList;
const byKey = <K extends keyof NodeState>(key: K) => createSelector(
nodeListState,
(nodeList) => nodeList[key],
);
Now getNodes
selects Node[]
and getText
selects string
.现在
getNodes
选择Node[]
并且getText
选择string
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.