首页 > 解决方案 > 如何摆脱用于修复循环类型引用的接口

问题描述

我试图通过推断其元素类型来摆脱用作 Array 的接口。

是,但应该type test是。(string | string[])[]string[][]

我怎样才能解决这个问题?

type test = MyType<{ type: 'array'; items: { type: 'array'; items: { type: 'string' } } }>

type MyType<T> = T extends { type: 'string' }
  ? string
  : T extends { type: 'array' }
  ? UnpackMyArray<T extends { items: infer Items } ? MyArray<Items> : never>
  : never

interface MyArray<Declaration> extends Array<MyType<Declaration>> {}
type UnpackMyArray<T> = T extends Array<infer Item> ? Item[] : never

标签: typescript

解决方案


我希望我知道那里发生了什么,但我无法弄清楚。通过在接口中包装一个原本被禁止的自引用条件类型然后立即展开它来绕过循环类型检测器是一个技巧并且可能很脆弱。我已经看到针对其他此类技巧的警告;不知道这个最终会如何,但我会警惕依赖它。(注意,如果您只是返回您的类型,这不会是一个问题MyArray......这是可疑的额外展开)。

无论如何,我试图分析它,但即使我对代码所做的微小更改最终都会使编译器感到困惑,以至于输出类型就像any整个事情一样。最后,我重新创建了您的逻辑并尽可能多地删除了条件类型推断,将其替换为属性查找类型。类型推断比属性查找更“神奇”,而且我对推断结果的信心不如查找结果。具体来说,我进行了以下更改:

  • 而不是T extends {prop: infer P} ? P :我会使用T extends {prop: unknown} ? T['prop'] :

  • 而不是T extends Array<infer L> ? L :我会使用T extends Array<any> ? T[number] :.

此外,我在可能的情况下折叠了嵌套条件类型(但我看到你编辑了你的问题也这样做了),如

  • 而不是T extends {prop: infer P} ? P extends Q ? ... : never我崩溃到T extends {prop: Q} ? ....

现在让我们看看你得到了什么:

type DeclarationType<D> = D extends { type: 'string' } ? string :
  (D extends { type: 'array', items: unknown } ? MyArray<D['items']> : never)[number][];

interface MyArray<D> extends Array<DeclarationType<D>> { }

type test = DeclarationType<{ 
  type: 'array'; items: { type: 'array'; items: { type: 'string' } } 
}>

type test = string[][]正如你所期望的那样,这给了我。

游乐场链接


完美吗?可能不是。你能期望它继续在新版本的 TypeScript 中工作吗?谁知道。我是否从 2019 年 4 月 26 日起在 TS 3.3.3 上运行的版本以及我的笔记本电脑上现在使用的任何版本的 TS(TS 3.5.0-dev.20190424)从技术上回答了您的问题?嗯,是的!

希望有帮助;祝你好运。


推荐阅读