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

TypeScript通用单属性提取函数的类型定义问题

TypeScript 通用单属性提取函数的类型错误修复

需求说明

需要实现一个通用函数,用于从对象中筛选提取单个属性。初始无类型版本如下:

function pickOnePropertyUntyped(data: any, key: any): any {
  return {
    [key]: data[key]
  }
}

期望行为示例:

interface A {
  a: string;
  b: number;
}
const a: A = {
  a: 'a',
  b: 1
}
const r = pickOnePropertyUntyped(a, 'a'); // 返回 {'a': 'a'}

尝试的带类型约束实现

我尝试实现了带类型约束的版本,该版本能正确限制输入为单个key,也能正确推断输出类型,但返回值的类型标记存在错误:

type UnionToIntersection<U> = 
    (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never 

type NoUnion<Key> =
    [Key] extends [UnionToIntersection<Key>] ? Key : never; 

type PickOneProperty<T, P extends keyof T & string> = {
  [K in keyof T as K extends NoUnion<P> ? K : never]: T[K]
}

function pickOneProperty<T, K extends keyof T & string>(
   data: T,
   key: K,
): PickOneProperty<T, K> {
  return {
    [key]: data[key]
  }
}

解决方案

方案1:类型断言快速修复

直接对返回值添加类型断言,让TypeScript确认返回值符合目标类型:

function pickOneProperty<T, K extends keyof T & string>(
   data: T,
   key: K,
): PickOneProperty<T, K> {
  return {
    [key]: data[key]
  } as PickOneProperty<T, K>
}

方案2:简化类型定义

简化返回类型的定义,直接构造单属性对象类型,同时优化泛型约束位置,让类型推断更顺畅:

type UnionToIntersection<U> = 
    (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never 

type NoUnion<Key> =
    [Key] extends [UnionToIntersection<Key>] ? Key : never; 

function pickOneProperty<T, K extends NoUnion<keyof T & string>>(
   data: T,
   key: K,
): { [P in K]: T[P] } {
  return {
    [key]: data[key]
  } as { [P in K]: T[P] }
}

这里将K的约束直接放在泛型定义中,确保输入只能是单个key,返回类型{ [P in K]: T[P] }更直观,TypeScript能更好地匹配。

方案3:利用Object.assign避免断言

通过Object.assign创建对象,帮助TypeScript自动推断正确的返回类型,无需手动断言:

type UnionToIntersection<U> = 
    (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never 

type NoUnion<Key> =
    [Key] extends [UnionToIntersection<Key>] ? Key : never; 

function pickOneProperty<T, K extends NoUnion<keyof T & string>>(
   data: T,
   key: K,
): { [P in K]: T[P] } {
  return Object.assign({}, { [key]: data[key] })
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 23:15:52