使用泛型推断正确类型:Reducer中Payload类型推断异常问题
解决Reducer中Action Payload类型推断问题
问题核心是你当前用泛型定义ToolAction,导致Reducer内部switch分支无法根据action.type收窄payload的具体类型。泛型T在Reducer内部是ToolCategory的联合类型,TypeScript没法将泛型与case的具体值关联,所以payload始终是联合类型。
解决方案:将Action定义为联合类型
把泛型的ToolAction改成基于ToolCategory的联合类型,让TypeScript能通过action.type自动收窄每个分支的action类型:
type ToolCategory = 'CursorTools' | 'DrawingTools' type CursorToolName = 'Cursor' | 'Measure' type DrawingToolName = 'Brush' | 'Pencil' type ToolMap = { CursorTools: CursorToolName; DrawingTools: DrawingToolName } interface ToolState { CursorTools: Tool<'CursorTools'> DrawingTools: Tool<'DrawingTools'> } interface Tool<T extends ToolCategory> { name: ToolMap[T]; onEnter?: () => void; } // 用映射类型自动生成每个ToolCategory对应的Action类型,组成联合类型 type ToolAction = { [T in ToolCategory]: { type: T; payload: Tool<T>; }; }[ToolCategory]; const reducer = ( state: ToolState, action: ToolAction ): ToolState => { switch(action.type){ case 'CursorTools': { // 这里action.payload会被正确推断为Tool<'CursorTools'>,name是CursorToolName类型 return { ...state, CursorTools: { name: action.payload.name } }; } case 'DrawingTools': { // 同理,这里payload.name是DrawingToolName类型 return { ...state, DrawingTools: { name: action.payload.name } }; } default: return state; } } // dispatch阶段的类型检查依然有效,传入错误name会报错 reducer( {CursorTools: {name: 'Cursor'}, DrawingTools: {name: 'Brush'}}, {type: 'CursorTools', payload: {name: 'Cursor'}} )
为什么原来的泛型方案不行?
你的原代码中,Reducer是泛型函数,T在调用时是具体的ToolCategory值,但在Reducer内部,TypeScript无法确定T到底是CursorTools还是DrawingTools,所以switch的case分支无法收窄泛型的类型范围,导致action.payload始终是Tool<'CursorTools'> | Tool<'DrawingTools'>的联合类型。
改用联合类型的Action后,TypeScript会把每个type对应的action视为独立的类型分支,进入case时自动精确推断payload的类型。
内容的提问来源于stack exchange,提问作者Martin Hansson
相关产品推荐
相关产品推荐

