You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过映射类型约束Redux选择器参数并启用TS智能提示?

解决Redux扩展中Selector参数类型推断与命名约束问题

问题分析

你当前的类型定义存在循环约束(Selectors extends SelectorsConstraintMap<Selectors, State>),导致TypeScript无法先推断State类型,再将其传递给Selector的参数,最终参数state被推断为any。而Record<string, Selector<S>>能正常工作,是因为它直接将所有选择器值与State绑定,没有循环依赖。

解决方案

我们需要调整类型定义,先让TypeScript推断State,再约束选择器的键名和参数类型:

1. 定义合法选择器键名约束

用TypeScript模板字符串类型强制选择器名称必须符合selectCapitalCase模式:

type ValidSelectorKey = `select${Capitalize<string>}`;

2. 调整Selector与映射类型

保留Selector的基础定义,同时定义基于State的选择器映射类型,确保每个选择器的参数都绑定到当前State:

type Selector<S, R = any> = (state: S) => R;

// 约束选择器集合:键必须符合命名规范,值必须是对应State的Selector
type SelectorsForState<S> = {
  [K in ValidSelectorKey]: Selector<S>;
};

3. 重新定义Initializer

让Initializer先推断State,再将State应用到选择器的约束上,避免循环依赖:

type Initializer = <State extends object>(content: {
  state: State;
  selectors: SelectorsForState<State>;
}) => void;

declare const init: Initializer;

使用示例

此时选择器的state参数会自动推断为对应State类型,同时强制命名规范:

init({
  state: {
    x: 123,
    y: 456
  },
  selectors: {
    // state自动推断为{ x: number; y: number },有完整智能提示
    selectX: (state) => state.x,
    selectY: (state) => state.y,
    
    // 以下写法会报错:键名不符合selectCapitalCase规范
    // foo: (state) => "foo"
  }
});

验证约束

如果尝试给选择器参数指定错误类型,TypeScript会正常报错:

init({
  state: { x: 123, y: 456 },
  selectors: {
    // 错误:Type '{ x: number; y: number; }' is not assignable to type 'number'.
    selectX: (state: number) => state
  }
});

内容的提问来源于stack exchange,提问作者Dellirium

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 15:08:17