简体   繁体   English

在 TypeScript 中使用 createSelector 创建选择器工厂

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM