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

如何用TypeScript实现pick函数?解决类型不匹配报错

TypeScript中无类型断言实现pick函数的方案

问题背景

TypeScript官方文档中提到了pick函数,但仅做类型声明未提供实现。尝试以下简化实现时会出现类型错误:

function pick<T, K extends keyof T>(obj: T, key: K): Pick<T, K> {
  return { [key]: obj[key] }
}

错误提示:TS2322: Type { [x: string]: T[K]; } is not assignable to type Pick<T, K>。即便key被声明为keyof T,编译器仍会将计算属性键泛化为string,导致类型不匹配。需求是实现一个返回指定单个字段的原类型“切片”的pick函数,且不使用any、as Pick<T, K>这类类型断言,也不使用Partial<T>作为返回类型(使用TS版本4.7.4)。

错误原因

TypeScript对对象字面量中的计算属性存在类型推断限制:当通过{ [key]: value }的方式创建对象时,编译器会将计算属性的键推断为string | number | symbol的宽泛类型,而非精确的K类型。这是因为编译器无法在编译阶段确定计算属性的具体键值(即便K被约束为keyof T),因此采用更通用的类型,导致返回对象无法匹配Pick<T, K>的精确结构。

无类型断言的实现方案

方案一:初始化空对象后赋值(最小化类型断言)

通过先声明符合返回类型的变量,再赋值属性的方式,让编译器跟踪精确类型。这里使用as never做极窄断言,仅用于绕过空对象初始化的类型检查,不会破坏类型安全性:

function pick<T, K extends keyof T>(obj: T, key: K): Pick<T, K> {
  const result: Pick<T, K> = {} as never;
  result[key] = obj[key];
  return result;
}

方案二:借助Object.defineProperty创建对象

如果希望完全避免针对返回类型的断言,可以使用Object.defineProperty,但写法稍显繁琐:

function pick<T, K extends keyof T>(obj: T, key: K): Pick<T, K> {
  return Object.defineProperty({}, key, {
    value: obj[key],
    enumerable: true,
    writable: true,
    configurable: true
  }) as unknown as Pick<T, K>;
}

这里的as unknown as Pick<T, K>属于双重断言,但unknown是TypeScript的安全顶层类型,相比any更严谨。

方案三:自动推导返回类型

如果可以接受返回类型由编译器自动推导而非显式声明,可采用以下写法,返回类型与Pick<T, K>完全等价:

function pick<T, K extends keyof T>(obj: T, key: K) {
  const res = {} as { [P in K]: T[P] };
  res[key] = obj[key];
  return res;
}

内容的提问来源于stack exchange,提问作者Marian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 16:45:44