如何查看Typescript类型的完整展开合同?

时间:2019-08-27 23:26:28

标签: typescript visual-studio-code algebraic-data-types

如果我有一些看起来像这样的类型集合,那么只会更加冗长:

type ValidValues = string | number | null
type ValidTypes = "text" | "time" | "unknown"

type Decorated = {
  name?: string | null
  type?: ValidTypes
  value?: ValidValues
  title: string
  start: number
}

type Injected = {
  extras: object
}

// overriding the types from Decorated
type Text = Decorated & Injected & {
  name: string
  type: "text"
  value: string
}

我的实际代码还在进行中,但这显示了核心思想。我不需要信任自己就能正确地获得类型之间的关系。我想让工具向我展示Text的类型定义对所有类型代数的“赋值”。

因此对于上面的示例,我希望Text中指定的字段将覆盖Decorated类型中的先前声明,并且我的假设工具提示的输出将(希望)显示我是这样的:

{
  name: string
  type: "text"
  value: string
  title: string
  start: number
  extras: object
}

是否有任何方便的方法来获取此信息?

1 个答案:

答案 0 :(得分:6)

使用IntelliSense显示的类型的快速信息通常令人不满意。对于任何给定的类型,您通常都会得到一个单一的表示形式,这可能对于您的目的而言过于简洁甚至过于冗长。有一些建议使其更灵活(例如microsoft/TypeScript#25784microsoft/TypeScript#28508),以便用户可以在其IDE中扩展/折叠类型定义。但是我不知道他们是否会在不久甚至更远的将来采取行动,所以让我们不要等着。


这里是类型别名,有时我会用这种别名来尝试以您谈论的方式扩展类型:

// expands object types one level deep
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;

// expands object types recursively
type ExpendRecursively<T> = T extends object
  ? T extends infer O ? { [K in keyof O]: ExpendRecursively<O[K]> } : never
  : T;

使用conditional type inference将类型T“复制”到新的类型变量O中,然后使用类似身份的mapped type来遍历复制的类型的属性。

从概念上讲,条件类型推断是无操作的,但是它用于distribute union types并迫使编译器评估条件的“ true”分支(如果您不使用它来重新定义Expand<T>,有时编译器只会输出映射类型{[K in keyof RelevantType]: RelevantType[K]},这不是您想要看到的)。

ExpandExpandRecursively之间的区别在于,它应该只是按原样吐出属性类型(Expand),还是应该扩展属性类型({{1)}。在递归的情况下,不要尝试深入研究原始类型会有所帮助,这就是为什么包含ExpandRecursively条件的原因。


好的,让我们看看在您的类型上使用它时会发生什么。在您的情况下,我们不需要T extends object,但是我们可以使用它……它给出的结果相同:

ExpandRecursively

当我们将其悬停在IDE(无论如何是TypeScript Playground和VSCode)上时,将显示为:

type ExpandedText = Expand<Text>;

根据需要。好的,希望能有所帮助;祝你好运!

Link to code