【问题标题】:Error in infer of rootState type | TS2339推断 rootState 类型时出错 | TS2339
【发布时间】:2020-07-24 07:08:20
【问题描述】:

我正在尝试推断 RootState 的类型,但在尝试在选择器中使用它时出现此错误:

const tagsSelector = (state: RootState) => state.tags;
TS2339: Property 'tags' does not exist on type 'CombinedState<{ tags: CombinedState<{ tagsSet: TagsState; }>; } | { queue: CombinedState<{ clientCard: ClientCardState; clientCardTasks: ClientCardTasksState; }>; }>'.   Property 'tags' does not exist on type '{ readonly [$CombinedState]?: undefined; } & { queue: CombinedState<{ clientCard: ClientCardState; clientCardTasks: ClientCardTasksState; }>; }'.

我推断的RootState类型

const typedReducers = typedModules.map(m => m.getTypedReducers() ).reduce((accum, r) => {
    return {...accum, ...r}
});

const rootTypedReducers = combineReducers(typedReducers);

export type RootState = ReturnType<typeof rootTypedReducers>;

getTypedReducers() 只返回每个模块的根减速器

getTypedReducers() {
        return {tags: combineReducers({
                    tagsSet: tagsReducers,
            })};
    }

但是,如果我只使用一个模块,那么一切正常。

【问题讨论】:

    标签: reactjs typescript redux redux-toolkit


    【解决方案1】:

    这就是 typescript 解释你的状态类型的方式:

    CombinedState<{ tags: CombinedState<{ tagsSet: TagsState; }>; } | { queue: CombinedState<{ clientCard: ClientCardState; clientCardTasks: ClientCardTasksState; }>; }>
    

    问题在于它是 OR 而不是 AND。您的状态被看到要么有键 'tags''queue' | 'clientCard' | 'clientCardTasks'。所以就打字稿而言,tags 不能保证始终存在。

    这种错误类型是在您的typedReducures 中创建的,因为您使用的是mapreduce 之类的数组函数。 Typescript 无法理解 return {...accum, ...r} 必须包含单个 getTypedReducers() 映射的所有元素。所以我们需要重写那里的返回类型。

    有一个由@jcalz 创建的经典UnionToIntersection utility type,我们可以在这里使用。

    type UnionToIntersection<U> =
      (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never
    
    type Reducers = UnionToIntersection<ReturnType<typeof typedModules[number]['getTypedReducers']>>
    
    const typedReducers = typedModules.map(m => m.getTypedReducers()).reduce((accum, r) => {
      return { ...accum, ...r }
    }) as Reducers;
    

    现在选择器中不再有错误,因为所有键都知道肯定存在。

    Typescript Playground Link

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多