TypeScript:如何基于对象属性键类型约束属性值类型?
解决TypeScript中关联属性名与属性值类型的问题
问题分析
你之前的方案失败是因为keyof StoreState生成的是键的联合类型,此时propValue会被推断为所有对应值类型的联合,无法和单个propName建立一一对应的约束关系——也就是说,TypeScript无法确保你传入的propValue和propName是匹配的。
解决方案:泛型函数约束
使用泛型捕获具体的属性键,让propValue的类型严格对应propName对应的StoreState属性类型:
type StoreState = { admins: Admin[]; messages: Message[]; pageInformation: PageInformation; } const state: StoreState = { admins: [], messages: [], pageInformation: {}, } // 泛型函数:K 代表 StoreState 的某个具体键 const setPropertyValue = <K extends keyof StoreState>({ propName, propValue }: { propName: K; propValue: StoreState[K] }) => { state[propName] = propValue; };
正确调用示例
// 符合类型约束,正常通过 setPropertyValue({ propName: "admins", propValue: [{ id: 1, name: "admin" } as Admin] }); setPropertyValue({ propName: "pageInformation", propValue: { title: "Home" } as PageInformation }); // 类型不匹配,TypeScript会报错 setPropertyValue({ propName: "admins", propValue: ["hello"] }); // 错误:string[] 不能赋值给 Admin[]
扩展:Redux Reducer的实现
如果你要把这个逻辑迁移到Redux reducer中,可以通过映射类型生成联合action类型来保证类型安全:
// 生成所有可能的SET_PROPERTY action类型 type SetPropertyAction = { [K in keyof StoreState]: { type: 'SET_PROPERTY'; payload: { propName: K; propValue: StoreState[K]; }; }; }[keyof StoreState]; const reducer = (state: StoreState, action: SetPropertyAction): StoreState => { switch (action.type) { case 'SET_PROPERTY': return { ...state, [action.payload.propName]: action.payload.propValue }; default: return state; } };
这种写法会让TypeScript自动检查action的payload是否匹配:当propName为"admins"时,propValue必须是Admin[]类型,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Király József
相关产品推荐
相关产品推荐

