rootState 类型推断错误 | TS2339
Error in infer of rootState type | TS2339
我正在尝试推断 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() 只是 return 每个模块的根 reducer
getTypedReducers() {
return {tags: combineReducers({
tagsSet: tagsReducers,
})};
}
但是,如果我只使用一个模块,那么一切正常。
打字稿是这样解释你的状态类型的:
CombinedState<{ tags: CombinedState<{ tagsSet: TagsState; }>; } | { queue: CombinedState<{ clientCard: ClientCardState; clientCardTasks: ClientCardTasksState; }>; }>
问题是它是 OR 而不是 AND。您的状态被视为 具有键 'tags'
或 'queue' | 'clientCard' | 'clientCardTasks'
。因此,就打字稿而言,tags
不能保证始终存在。
这个错误的类型是在您的 typedReducures
中创建的,因为您正在使用像 map
和 reduce
这样的数组函数。 Typescript 无法理解 return {...accum, ...r}
必须包含单个 getTypedReducers()
映射的所有元素。所以我们需要在那里覆盖 return 在那里输入。
@jcalz 创造了一个经典 ,我们可以在这里使用它。
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;
现在选择器中不再有错误,因为已知所有键确实存在。
我正在尝试推断 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() 只是 return 每个模块的根 reducer
getTypedReducers() {
return {tags: combineReducers({
tagsSet: tagsReducers,
})};
}
但是,如果我只使用一个模块,那么一切正常。
打字稿是这样解释你的状态类型的:
CombinedState<{ tags: CombinedState<{ tagsSet: TagsState; }>; } | { queue: CombinedState<{ clientCard: ClientCardState; clientCardTasks: ClientCardTasksState; }>; }>
问题是它是 OR 而不是 AND。您的状态被视为 具有键 'tags'
或 'queue' | 'clientCard' | 'clientCardTasks'
。因此,就打字稿而言,tags
不能保证始终存在。
这个错误的类型是在您的 typedReducures
中创建的,因为您正在使用像 map
和 reduce
这样的数组函数。 Typescript 无法理解 return {...accum, ...r}
必须包含单个 getTypedReducers()
映射的所有元素。所以我们需要在那里覆盖 return 在那里输入。
@jcalz 创造了一个经典
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;
现在选择器中不再有错误,因为已知所有键确实存在。