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

TypeScript实现带正确类型推导的对象子集提取函数,支持嵌套键

原实现错误原因

  1. 没有声明第二个泛型捕获传入keys的具体字面量类型,TS只会把keys推导为(keyof T)[],丢失了实际传入的键信息
  2. 返回值类型Record<keyof typeof keys, any>逻辑错误:typeof keys是数组类型,keyof 数组拿到的是数组实例的属性(length、索引签名等),和期望提取的对象键完全无关

平级键提取实现(满足基础需求)

直接用TS内置的Pick工具类型即可实现正确的类型推导:

function extractFromObj<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
  return keys.reduce((newObj, curr) => {
    newObj[curr] = obj[curr];
    return newObj;
  }, {} as Pick<T, K>);
}

使用效果和要求的示例完全一致,解构时只会提示你传入的键,类型完全匹配原对象对应键的类型:

// 示例调用
const post = { id: 1, properties: {}, created_time: '', otherKey: '' };
const { id, properties, created_time } = extractFromObj(post, ['id', 'properties', 'created_time']);
// 此时上面三个变量的类型会自动匹配post中对应键的类型,不会出现多余的otherKey提示

嵌套键提取实现(满足补充需求)

需要先定义两个TS工具类型,用于推导合法的路径和路径对应值的类型,再实现路径取值逻辑:

// 工具类型:推导对象所有合法的点分隔路径
type PathImpl<T, Key extends keyof T> = Key extends string
  ? T[Key] extends Record<string, any>
    ? | `${Key}.${PathImpl<T[Key], keyof T[Key]>}`
      | Key
    : Key
  : never;
type Path<T> = PathImpl<T, keyof T>;

// 工具类型:根据点分隔路径推导对应值的类型
type PathValue<T, P extends string> = P extends `${infer Key}.${infer Rest}`
  ? Key extends keyof T
    ? PathValue<T[Key], Rest>
    : never
  : P extends keyof T
  ? T[P]
  : never;

// 根据路径从对象取值的工具函数
function getValueByPath(obj: any, path: string) {
  return path.split('.').reduce((curr, key) => curr?.[key], obj);
}

// 嵌套提取版本函数
function extractFromObjNested<T, P extends Path<T>>(obj: T, paths: P[]): { [K in P]: PathValue<T, K> } {
  return paths.reduce((newObj, path) => {
    newObj[path] = getValueByPath(obj, path as string);
    return newObj;
  }, {} as { [K in P]: PathValue<T, K> });
}

使用示例:

const obj = {
  "object": "page",
  "id": "b03f9945-528a-4a1c-a280-6972bbc49462",
  "created_time": "2021-11-07T11:24:00.000Z",
  "last_edited_time": "2021-11-07T11:24:00.000Z",
  "cover": null,
  "foo": {
    "bar": {
      "baz": {
        "properties": "hello world"
      }
    }
  }
}

const result = extractFromObjNested(obj, ['id', 'foo.bar.baz.properties']);
// result的类型会自动推导为:
// {
//   id: string;
//   'foo.bar.baz.properties': string;
// }
// 解构时类型完全正确
const { id, 'foo.bar.baz.properties': nestedProp } = result;

如果需要提取后保留嵌套结构而非用路径做键,只需要调整reduce中的赋值逻辑即可,类型推导部分可以复用上面的Path和PathValue工具。


内容的提问来源于stack exchange,提问作者nas.engineer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 09:36:02