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

使用泛型推断正确类型: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 22:09:22