You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 01:36:06