如何根据输入数组确定返回对象的键?TypeScript类型问题
问题描述
需要实现一个函数:接收由'add'/'remove'/'update'/'get'组成的数组作为参数,返回一个对象——对象的键与输入数组中的值完全对应,每个键对应的属性值是预先定义好的外部函数(每个函数有独立类型,无法在当前函数内部声明返回对象的完整类型)。
当前实现的问题:调用函数后返回的对象类型中,所有属性均为可选状态(如add?: any),但期望返回的对象仅包含传入数组中指定的属性,且这些属性为必填项。
示例代码
// 修正原类型定义:原Array<>写法有误,应定义为字符串联合类型 type Methods = 'add' | 'remove' | 'update' | 'get'; // 模拟外部函数(实际为用户提供的独立类型函数) const externalAddFunc = () => () => {}; const externalRemoveFunc = () => () => {}; const externalUpdateFunc = () => () => {}; const externalGetFunc = () => () => {}; const createAction = <M extends Methods[]>(methods: M) => { return { ...(methods.includes('add') && { add: externalAddFunc(), }), ...(methods.includes('remove') && { remove: externalRemoveFunc(), }), ...(methods.includes('update') && { update: externalUpdateFunc(), }), ...(methods.includes('get') && { get: externalGetFunc(), }), }; } const newAction = createAction(['add', 'remove']); // 实际推导类型: { add?: any; remove?: any; update?: any; get?: any; } // 期望推导类型: { add: ReturnType<typeof externalAddFunc>; remove: ReturnType<typeof externalRemoveFunc>; }
解决方案
通过映射类型和精准泛型约束,让TypeScript正确推导仅包含传入方法的必填属性类型:
1. 定义方法与函数类型的映射
先统一维护方法到对应函数类型的映射,确保类型关联准确:
type MethodFuncMap = { add: ReturnType<typeof externalAddFunc>; remove: ReturnType<typeof externalRemoveFunc>; update: ReturnType<typeof externalUpdateFunc>; get: ReturnType<typeof externalGetFunc>; };
2. 调整函数的泛型与返回逻辑
修改createAction的泛型约束,让TypeScript识别传入的数组为字面量元组,再通过Pick类型提取目标属性:
const createAction = <M extends Methods>(methods: readonly M[]) => { const result = {} as Pick<MethodFuncMap, M>; if (methods.includes('add')) result.add = externalAddFunc(); if (methods.includes('remove')) result.remove = externalRemoveFunc(); if (methods.includes('update')) result.update = externalUpdateFunc(); if (methods.includes('get')) result.get = externalGetFunc(); return result; }
效果验证
现在调用createAction(['add', 'remove'])时,newAction的类型会被精准推导为:
{ add: ReturnType<typeof externalAddFunc>; remove: ReturnType<typeof externalRemoveFunc>; }
完全符合期望,所有属性均为必填项。
关键说明
- 使用
readonly M[]是为了让TypeScript将传入数组识别为字面量元组(而非宽泛的Methods[]),从而精准推导泛型M。 - 通过
Pick<MethodFuncMap, M>直接从预定义映射中提取目标属性,避免手动维护返回类型。 - 替换扩展语法为条件赋值,配合类型断言让TypeScript认可赋值操作的合法性。
内容的提问来源于stack exchange,提问作者johnzanussi
相关产品推荐
相关产品推荐

