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

TypeScript泛型场景下定义helper方法报类型不兼容错误如何解决?

问题根因

你当前create函数的泛型约束会让TypeScript自动将传入的actionHandlers对象的键类型拓宽为普通string,而非保留"SET_MSG" | "SET_NUM" | "SET_FLAG"的字面量联合类型,导致GenericDispatch的类型参数Key被推导为string,和实际的action类型字面量不匹配,触发类型错误。

解决方案

修改create函数的泛型约束,让TypeScript保留ActionHandlers与Helpers的键字面量类型,不自动拓宽:

type Args<State, ActionHandlers, Helpers> = {
    state: State,
    actionHandlers: ActionHandlers,
    helpers?: Helpers
}

type GenericActionHandler<State, Payload> = (state: State, payload: Payload) => Partial<State> | void

type GenericDispatch<State, ActionHandlers> = <
    Key extends keyof ActionHandlers,
    Handler extends ActionHandlers[Key],
    Payload = Handler extends GenericActionHandler<State, infer P> ? P : never
>(type: Key, ...payload: Payload extends undefined ? [] : [Payload]) => void

type GenericHelper<State, ActionHandlers, Payload> = (dispatch: GenericDispatch<State, ActionHandlers>, payload: Payload) => Promise<void> | void

type HelpersRemapped<State, ActionHandlers, Helpers> = {
    [Key in keyof Helpers]: <
        Helper extends Helpers[Key],
        Payload = Helper extends GenericHelper<State, ActionHandlers, infer P> ? P : never 
    >(payload: Payload) => Promise<void> | void
}

// 仅修改此处的泛型约束
const create = <
    State extends {},
    ActionHandlers extends Record<keyof ActionHandlers, GenericActionHandler<State, any>>,
    Helpers extends Record<keyof Helpers, GenericHelper<State, ActionHandlers, any>> = never
>({ state, actionHandlers, helpers }: Args<State, ActionHandlers, Helpers>) => {

    const dispatch: GenericDispatch<State, ActionHandlers> = (type, ...payload) => { console.log(type, [payload]) };

    type Remap = HelpersRemapped<State, ActionHandlers, Helpers>;

    const helpersRemapped: Partial<Remap> = {}
    for (const key in helpers) {
        helpersRemapped[key] = (payload) => helpers[key](dispatch, payload);
    }

    return {
        dispatch,
        helpers: helpersRemapped as Remap
    };
}

let { dispatch, helpers } = create({
    state: {
        msg: "hi",
        num: 123,
        flag: true
    },
    actionHandlers: {
        SET_MSG: (state, msg: string) => ({ msg }),
        SET_NUM: (state, num: number) => ({ num }),
        SET_FLAG: (state, flag: boolean) => ({ flag })
    },
    helpers: {
        setFlagAsync: async (dispatch, flag: boolean) => {
            await Promise.resolve();
            dispatch("SET_FLAG", flag);
        }
    }
});

helpers.setFlagAsync(true);
dispatch("SET_MSG", "test");
验证效果

修改后:

  • helpers内定义方法不再触发类型报错
  • 调用dispatch时会自动提示所有合法的action类型,payload参数也会对应校验类型
  • 调用helpers下的方法也会有正确的参数类型提示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 13:36:01