从具有正确类型推断的键数组创建一个新的子集对象

nas*_*eer 4 typescript

给定一个对象和一个键的字符串数组(这些键将存在于对象中),使用正确的 Typescript 类型构造一个包含这些键及其对应值的新对象。那是:

/**
 * This function will construct a new object
 * which is the subset values associated to 
 * the keys array
**/
function extractFromObj<T>(obj: T, keys: (keyof T)[])

// in here, suppose `post` is a huge object,
// but the intellicence should only show keys
// from the keys array
const { id, properties, created_time } = extractFromObj(post, ['id', 'properties', 'created_time'])
Run Code Online (Sandbox Code Playgroud)

我的解决方案(到目前为止是错误的)

function extractFromObj<T>(obj: T, keys: (keyof T)[]): Record<keyof typeof keys, any> {
  return keys.reduce((newObj, curr) => {
    newObj[curr] = obj[curr]

    return newObj
  }, {} as Record<keyof typeof keys, any>)
}

const {} = extractFromObj(post, ['id', 'properties', 'created_time']) // wrong
Run Code Online (Sandbox Code Playgroud)

需要帮助,请&谢谢

更新

我忘了提及,当键嵌套在对象内部时,该解决方案也应该有效。例如:

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"
      }
    }
  }
}

Run Code Online (Sandbox Code Playgroud)

Les*_*iak 5

您似乎正在寻找Pick<Type, Keys>实用程序类型。

您可以按如下方式实现您的功能:

const post = {
  id: 1,
  properties: 2,
  created_time: 'aaa',
  other_prop: 2
}

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 result1 = extractFromObj(post, ['id', 'properties', 'created_time'])
Run Code Online (Sandbox Code Playgroud)

最重要的是:

  • 您可能更喜欢使用 vargargs 而不是数组作为键
  • 如果你的目标是 ES2019,你可以使用Object.fromEntries
const post = {
  id: 1,
  properties: 2,
  created_time: 'aaa',
  other_prop: 2
}

function extractFromObjEs2019<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K> {
  const entries = keys.map(key => ([key, obj[key]]));
  return Object.fromEntries(entries);
}

const result2 = extractFromObjEs2019(post, 'id', 'properties', 'created_time')
Run Code Online (Sandbox Code Playgroud)

游乐场链接

更新:

对于递归版本,您可以从这个 Playground开始,基于Typescript 类型的递归子集