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

问题描述 投票:0回答:3

如果我有一个看起来有点像这样的类型集合:

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
}

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

typescript visual-studio-code algebraic-data-types
3个回答
195
投票

通过 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;

那些使用条件类型推断将类型

T
“复制”到新的类型变量
O
中,然后使用类似身份的映射类型,它会迭代复制类型的属性。

条件类型推断在概念上是无操作,但它用于分配联合类型并强制编译器评估条件的“true”分支(如果您在没有它的情况下重新定义

Expand<T>
,有时编译器会只是输出映射类型
{[K in keyof RelevantType]: RelevantType[K]}
,这不是你想看到的)。

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


好吧,让我们看看当我们在您的类型上使用它时会发生什么。 在您的情况下,我们不需要

ExpandRecursively
,但我们可以使用它......它给出相同的结果:

type ExpandedText = Expand<Text>;

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

/* type ExpandedText = {
  name: string;
  type: "text";
  value: string;
  title: string;
  start: number;
  extras: object;
 } */

如你所愿。

代码链接


63
投票

只是用可使用函数的版本补充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;

为了测试,我在

subobject
类型中添加了
Text
键,并添加了功能界面:

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

interface SomeFunction {
  (...args: Text[]): Injected & { error: boolean };
}

这给出:

enter image description here

expanded once type hover

recursive type hover

对象仍然可以正常工作:

enter image description here enter image description here


0
投票

我发现这个 VS Code 扩展非常适合这个:

美化 TypeScript:更好的类型预览

它甚至可以在悬停时显示深度嵌套的类型。

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.