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

sud*_*ian 41 algebraic-data-types typescript visual-studio-code

如果我有一个看起来有点像这样的类型集合,只会更详细:

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
}
Run Code Online (Sandbox Code Playgroud)

我的实际代码还有更多内容,但这显示了核心思想。我不想必须相信自己才能使类型之间的关系恰到好处。Text在所有类型代数之后,我想要工具向我展示“评估”的类型定义。

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

{
  name: string
  type: "text"
  value: string
  title: string
  start: number
  extras: object
}
Run Code Online (Sandbox Code Playgroud)

有什么方便的方法来获取这些信息吗?

jca*_*alz 65

使用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 ExpandRecursively<T> = T extends object
  ? T extends infer O ? { [K in keyof O]: ExpandRecursively<O[K]> } : never
  : T;
Run Code Online (Sandbox Code Playgroud)

那些使用条件类型推断将一个类型“复制”T到一个新的类型变量中O,然后是一个类似身份的映射类型,它遍历复制的类型的属性。

条件类型推断在概念上是无操作的,但它用于分发联合类型并强制编译器评估条件的“真”分支(如果您在Expand<T>没有它的情况下重新定义,有时编译器只会输出映射类型{[K in keyof RelevantType]: RelevantType[K]},这不是您想看到的)。

Expand和之间的区别在于ExpandRecursively它是否应该按原样吐出属性类型(Expand),或者是否应该扩展属性类型(ExpandRecursively)。它有助于在递归情况下不要尝试深入研究原始类型,这T extends object就是包含条件的原因。


好的,让我们看看当我们在你的类型上使用它时会发生什么。我们不需要ExpandRecursively你的情况,但我们可以使用它......它给出了相同的结果:

type ExpandedText = Expand<Text>;
Run Code Online (Sandbox Code Playgroud)

当我们在 IDE 中将鼠标悬停在它上面时(无论如何都是 TypeScript Playground 和 VSCode),它显示为:

/* type ExpandedText = {
  name: string;
  type: "text";
  value: string;
  title: string;
  start: number;
  extras: object;
 } */
Run Code Online (Sandbox Code Playgroud)

如你所愿。好的,希望有帮助;祝你好运!

代码链接

  • 如果您将其与 VS Code 一起使用,并且希望通过 IntelliSense 查看完整的扩展类型,您可能还需要在“tsconfig.json”中启用“noErrorTruncation”(请参阅​​ /sf/answers/3719227711/ ) (6认同)
  • 非常感谢,自从我开始使用 Typescript 以来,我就一直想要这样的东西 - 真是一个很酷的黑客。 (2认同)
  • 哦,伙计,你的 Expand 应该是内置实用程序类型 Alias&lt;T&gt; 或其他类型。 (2认同)
  • 这很简洁,但它将函数变成空对象,因为它们扩展了对象但没有任何属性。 (2认同)
  • 也许像[这个版本](https://tsplay.dev/WPgRYm)?如果您需要更多或其他内容,请打开一个关于它的新问题帖子。 (2认同)

MHe*_*bes 59

只是用与函数一起使用的版本来补充jcalz 的答案。

修改后的助手:

export type Expand<T> = T extends (...args: infer A) => infer R
  ? (...args: Expand<A>) => Expand<R>
  : T extends infer O
  ? { [K in keyof O]: O[K] }
  : never;

export type ExpandRecursively<T> = T extends (...args: infer A) => infer R
  ? (...args: ExpandRecursively<A>) => ExpandRecursively<R>
  : T extends object
  ? T extends infer O
    ? { [K in keyof O]: ExpandRecursively<O[K]> }
    : never
  : T;
Run Code Online (Sandbox Code Playgroud)

为了进行测试,我添加了一个subobject键入键Text,并添加了一个函数接口:

type Text = Decorated &
  Injected & {
    name: string;
    type: "text";
    value: string;
    subobject: Injected;
  };

interface SomeFunction {
  (...args: Text[]): Injected & { error: boolean };
}
Run Code Online (Sandbox Code Playgroud)

这给出:

在此输入图像描述

展开一次类型悬停

递归类型悬停

对象仍然可以正常工作:

在此输入图像描述 在此输入图像描述

  • 哇,这太棒了,也许有一种方法可以编写一个与 IntelliSense 集成的扩展来实现这个...... (5认同)
  • @RobertKoritnik [backus的评论](/sf/ask/4037831241/#comment107641913_57683652)有一个很好的jcalz 答案的评论中为您提供了解决方案:*如果您将其与 VS Code 一起使用,并且希望通过 IntelliSense 查看完整的扩展类型,您可能还需要在“tsconfig.json”中启用“noErrorTruncation”(请参阅​​ stackoverflow.htm)。 com/a/53131824/146044)* (2认同)