如何从泛型自动设置TypeScript中UserAction的type字段?
自动填充UserAction的type字段方案
首先,咱们先回顾下你现有的代码结构(方便理解问题根源):
interface IUserAction<T, P> { readonly type: T; readonly payload: P; } export type UserAction<T, P> = IUserAction<T, P>; export enum UserActions { SetCountry = 'SetCountry', }; // 原写法:必须手动添加type,否则报错 const action: UserAction<UserActions.SetCountry, SetCountryActionPayload> = { payload: {countryId: Country.Usa} };
你遇到的问题很典型:每次创建action都得重复写type: UserActions.SetCountry,既繁琐又容易出错。想要实现传入泛型参数后自动填充type字段,其实可以通过创建action工厂函数来解决,下面给你两种实用方案:
方案一:针对单一action的专用工厂函数
如果你的SetCountry是独立的action类型,写一个专用的创建函数最直接:
// 先定义你的SetCountryActionPayload和Country枚举(补全你代码里的缺失部分) enum Country { Usa = 'USA' } type SetCountryActionPayload = { countryId: Country }; // 封装SetCountry的action创建函数,内置固定type const createSetCountryAction = (payload: SetCountryActionPayload): UserAction<UserActions.SetCountry, SetCountryActionPayload> => ({ type: UserActions.SetCountry, // 这里手动写一次,之后调用就不用管了 payload }); // 使用时只需要传payload,type自动带上 const action = createSetCountryAction({ countryId: Country.Usa });
这种方式的优点是简单直接,调用时完全不用关心type字段,TypeScript会自动保证返回的action符合UserAction类型要求。
方案二:支持所有action的通用工厂函数
如果以后要扩展更多UserActions枚举值(比如SetUser、SetLanguage等),通用工厂函数会更灵活:
// 先定义所有action对应的payload类型映射表 type ActionPayloadMap = { [UserActions.SetCountry]: SetCountryActionPayload; // 后续新增action时,直接在这里添加对应的payload类型即可 // [UserActions.SetUser]: SetUserPayload; }; // 通用action创建函数,自动推断type和payload的对应关系 const createAction = <T extends UserActions>(type: T, payload: ActionPayloadMap[T]): UserAction<T, ActionPayloadMap[T]> => ({ type, payload }); // 使用时只需要传入type和对应payload,类型自动校验 const action = createAction(UserActions.SetCountry, { countryId: Country.Usa });
这个方案的好处是扩展性极强:新增action时只需要在ActionPayloadMap里添加一条映射,不用再写新的专用函数,而且TypeScript会严格校验每个type对应的payload是否正确,完全避免类型错误。
两种方案都能帮你省去手动写type字段的麻烦,你可以根据自己的业务场景选择~
内容的提问来源于stack exchange,提问作者Sergei Basharov
相关产品推荐
相关产品推荐

