You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将按指定属性取值生成新对象的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 19:36:04