打字稿选择可选的未设置变量

Typescript Pick optionnal unset variable

我正在尝试使用打字稿的“选择”功能来获取我的对象的所有可能值。 我的对象具有可选属性,因此不一定要设置它们

const foo = [
    {
      name: 'index',
    },
    {
      name: 'id',
      type: 'number',
    },
    {
      name: 'error',
    },
  ] as const

type ElementArg<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<infer ElementType>
  ? Pick<ElementType, 'name' | 'type'>
  : never

type result = ElementArg<typeof foo>
//result : {name: "index" | "id" | "error"}
//expected : {name: "index" | "id" | "error" type: "number" | "undefined"}

而且我还尝试将“类型”属性转换为具有以下类型的类型:

type typeDecoder<T> = T extends 'number' ? number
  : T extends 'number[]' ? number[]
    : T extends 'string' ? string
      : T extends 'string[]' ? string[]
        : T extends 'boolean' ? boolean
          : T extends 'undefined' ? undefined
            : never;

但我认为有更好的方法,但我不知道在哪里使用我的函数

我设法让一些东西起作用:

type ElementArg<T extends ReadonlyArray<unknown>, R extends {} = {}> = T extends readonly [infer First, ...infer Rest]
  ? ElementArg<Rest, {
    [K in keyof First | keyof R]:
      K extends keyof R
        ? K extends keyof First
          ? R[K] | First[K]
          : R[K] | "undefined"
        : K extends keyof First
          ? First[K]
          : never
  }>
  : R;

主要思想是循环遍历元组中的每个元素,然后将其添加到我们累积的结果中。

T extends readonly [infer First, ...infer Rest]

这里我们得到第一个元素,其余元素作为一个元组。接下来是这个大块:

  ElementArg<Rest, {
    [K in keyof First | keyof R]:
      K extends keyof R
        ? K extends keyof First
          ? R[K] | First[K]
          : R[K] | "undefined"
        : K extends keyof First
          ? First[K]
          : never
  }>

我们对其余元素再次使用 ElementArg,然后 long 复杂映射类型正确地将此元素的内容添加到结果中。

逻辑是这样的:

  • 对于元素或结果中的每个键

  • 如果key是结果的key

    • 如果键是元素的键

      • 将键的值添加到结果中
    • 否则

      • "undefined"添加到结果
  • 否则如果键是元素的键

    • 这是我们添加到结果中的新键

最后,如果我们尝试获取第一个元素的第一步不起作用,这意味着 T 为空并且我们完成了,所以我们 return R

Playground