如果我有一些看起来像这样的类型集合,那么只会更加冗长:
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
}
是否有任何方便的方法来获取此信息?
答案 0 :(得分:6)
使用IntelliSense显示的类型的快速信息通常令人不满意。对于任何给定的类型,您通常都会得到一个单一的表示形式,这可能对于您的目的而言过于简洁甚至过于冗长。有一些建议使其更灵活(例如microsoft/TypeScript#25784和microsoft/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]}
,这不是您想要看到的)。
Expand
和ExpandRecursively
之间的区别在于,它应该只是按原样吐出属性类型(Expand
),还是应该扩展属性类型({{1)}。在递归的情况下,不要尝试深入研究原始类型会有所帮助,这就是为什么包含ExpandRecursively
条件的原因。
好的,让我们看看在您的类型上使用它时会发生什么。在您的情况下,我们不需要T extends object
,但是我们可以使用它……它给出的结果相同:
ExpandRecursively
当我们将其悬停在IDE(无论如何是TypeScript Playground和VSCode)上时,将显示为:
type ExpandedText = Expand<Text>;
根据需要。好的,希望能有所帮助;祝你好运!