【问题标题】:Why doesn't Typescript check assignment for this deeply nested type definition?为什么 Typescript 不检查这个深度嵌套类型定义的赋值?
【发布时间】:2022-10-24 11:45:06
【问题描述】:

我为涉及递归嵌套类型的特定用例创建了类型结构:

type ErrorNodeDetails = {example: number}

type ErrorNode<FormData> = FormData extends Array<infer ArrayItem>
  ? ErrorNode<ArrayItem>
  : FormData extends Primitive
  ? ErrorNodeDetails
  : ErrorNodeDetails & {
      children?: Readonly<{
        [K in keyof FormData]?: ErrorNode<FormData[K]>
      }>
    }

export type ErrorMap<FormData extends Record<string, unknown>> = {
  [K in keyof FormData]?: ErrorNode<FormData[K]>
}

生成的结构似乎与我期望的一样正确,我可以通过将对象定义为ErrorMap 类型来验证,在这种情况下,TS 只允许我访问预期的键,即使是深度嵌套的,但是对于分配,TS没有为更深层次(超过 4 个层次)充分执行检查:

const x: ErrorMap<{ x: { d: { c: 1 } } }> = {
      x: {
        example: 1,
        children: {
          d: {
            children: { // Up to this level, TS enforces the correct types. I can't change `children` to `c`.
              c1: { s: 1 }, // c1 shouldn't be allowed, but it is, as is anything within it.
            },
            example: 1,
          },
        },
      },
    }

    x.x?.children?.d?.children?.c // When accessing the values, even deep, TS gives the autocomplete as expected, and doesn't allow to access inexistent keys.

这是打字稿的一些限制,还是我错过了什么?

【问题讨论】:

  • 我不确定你要的是什么; this是你想要达到的目的吗?
  • @caTS 嗯,是的,实际上这似乎可以解决问题。在我问了这个问题之后,我认为这可能是问题所在:github.com/microsoft/TypeScript/issues/47935 它看起来仍然可能是相关的,但也许你的解决方案是解决这个问题的方法?您介意写一个答案,并解释一下为什么会这样吗?

标签: javascript typescript


【解决方案1】:

TS 在这里推迟计算映射类型:

type ErrorNode<FormData> = FormData extends Array<infer ArrayItem>
  ? ErrorNode<ArrayItem>
  : FormData extends Primitive
  ? ErrorNodeDetails
  : ErrorNodeDetails & {
      children?: Readonly<{
        [K in keyof FormData]?: ErrorNode<FormData[K]>
      }>
    }

但是我们可以通过这个小技巧强制它计算完整的内容:

type ErrorNode<FormData> = FormData extends Array<infer ArrayItem>
    ? ErrorNode<ArrayItem>
    : FormData extends Primitive
    ? ErrorNodeDetails
    : (ErrorNodeDetails & {
          children?: Readonly<
              {
                  [K in keyof FormData]?: ErrorNode<FormData[K]>;
              }
          >;
      }) extends infer O ? { [K in keyof O]: O[K] } : never; // magic

Playground

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-08
    • 2020-01-26
    • 1970-01-01
    • 2020-02-15
    • 2016-11-12
    • 2018-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多