如何将按指定属性取值生成新对象的JS函数改写为无TS类型错误的版本
TypeScript keyed函数类型改写方案
错误原因分析
- 错误
ts(1337):TS不允许直接将泛型类型作为索引签名的参数类型,索引签名仅支持固定的string/number/symbol三类,动态类型的键需要使用映射类型或者Record工具类实现。 - 错误
ts(2536):初始化的空对象{}默认没有匹配ValueOf<T>的索引签名,无法直接用非预设类型的值作为键赋值。
严格版实现(带输入合法性校验)
// 合法的对象键类型 type ValidObjectKey = string | number | symbol export function keyed< T extends object, K1 extends keyof T, K2 extends keyof T >( object: T, // 约束传入的key对应的值必须是可以作为对象键的类型,不符合要求会在调用阶段直接报错 key: T[K1] extends ValidObjectKey ? K1 : never, value: K2 ): Record<T[K1], T[K2]> { const newKey = object[key] as ValidObjectKey const newValue = object[value] return { [newKey]: newValue } as Record<T[K1], T[K2]> }
简化版实现(适合确定输入合法的业务场景)
export function keyed<T extends Record<any, any>, K1 extends keyof T, K2 extends keyof T>( obj: T, key: K1, value: K2 ) { return { [obj[key]]: obj[value] } as Record<T[K1], T[K2]> }
类型校验效果示例
const sample = { uid: 'admin', nickname: '管理员', level: 3 } // 返回值类型自动推导为 { admin: string } const userMap = keyed(sample, 'uid', 'nickname') // 返回值类型自动推导为 { 3: string } const levelMap = keyed(sample, 'level', 'nickname')
内容的提问来源于stack exchange,提问作者sanjayio
相关产品推荐
相关产品推荐

