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
相关产品推荐
相关产品推荐

