Typescript CompilerAPI 如何获取展开后的类型AST
问题描述
我的应用中的类型定义方式较为特殊:我在函数上定义代数结构,构造decoder函数后从decoder推断类型(可参考gcanti/io-fp的实现逻辑),目前typedoc项目存在相关的已知问题。
我需要编写工具为我的API生成规范的.d.ts文档,希望将如下输出:
export declare type BorderStyleEnum = 'None' | 'Solid'; export declare type BorderStyle = { Color?: string; Style?: BorderStyleEnum; Width?: string; }; export declare type BorderSideStyle = { Color?: string; Style?: '' | 'None' | 'Solid'; Width?: string; }; export declare type BorderSideStyleEnum = NonNullable<BorderSideStyle['Style']>; export declare type Style = { Border: BorderStyle; TopBorder: BorderSideStyle; LeftBorder: BorderSideStyle; BottomBorder: BorderSideStyle; RightBorder: BorderSideStyle; }; export declare type StyleExp = ExpandRecursively<Style>; declare function item(): { /** type of the element */ type: 'item'; name: string; style: Style; }; export declare type Expand<T> = T extends infer O ? { [K in keyof O]: O[K]; } : never; export declare type ExpandRecursively<T> = T extends object ? T extends infer O ? { [K in keyof O]: ExpandRecursively<O[K]> } : never : T; export declare type Item = ExpandRecursively<ReturnType<typeof item>>; export {};
简化为如下更紧凑的形式(手动整理的目标版本):
export type BorderStyleEnum = "None" | "Solid"; export type BorderStyle = { Color?: string; Style?: BorderStyleEnum; Width?: string; }; export type BorderSideStyle = { Color?: string; Style?: BorderSideStyleEnum; Width?: string; }; export type BorderSideStyleEnum = "" | "None" | "Solid"; export type Style = { Border: BorderStyle; TopBorder: BorderSideStyle; LeftBorder: BorderSideStyle; BottomBorder: BorderSideStyle; RightBorder: BorderSideStyle; }; export type StyleExp = Style; export type Item = { type: "item"; name: string; style: Style };
目前我使用以下代码片段获取类型定义:
const type = typeChecker.getTypeAtLocation(node); const typeDecl = typeChecker.typeToString(type, node, ts.TypeFormatFlags.NoTruncation // | ts.TypeFormatFlags.MultilineObjectLiterals | ts.TypeFormatFlags.InTypeAlias // | ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope // prevents type expansion // | ts.TypeFormatFlags.UseStructuralFallback );
该代码运行效果良好,可以展开类似export type Item = ExpandRecursively<ReturnType<typeof item>>;的复杂类型,但我的目标是获取展开后定义的AST,以便应用自定义的简化规则。
解决方案
实测NodeBuilderFlags.InTypeAlias可以满足需求,在typeToTypeNode的flags参数中添加该标识后,即可获取到展开后类型的AST:
var rnode = typeChecker.typeToTypeNode(type, undefined, ts.NodeBuilderFlags.NoTruncation | ts.NodeBuilderFlags.InTypeAlias );
内容的提问来源于stack exchange,提问作者olegz
相关产品推荐
相关产品推荐

