TypeScript编译器API:如何获取父类名称?

时间:2018-09-09 08:19:11

标签: typescript

我正在尝试解析一些打字稿文件以生成一些特定的文档,为此,我需要找到属于特定类的所有子类。

我尝试使用此处建议的代码:https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#using-the-type-checker

但是它没有指定父类名(或类型)

/**
 * Documentation for C
 */
export class C {
    /**
     * constructor documentation
     * @param a my parameter documentation
     * @param b another parameter documentation
     */
    constructor(a: string, b: C) { }
}

export class D extends C{

}

输出:

[
    {
        "name": "C",
        "documentation": "Documentation for C",
        "type": "typeof C",
        "constructors": [
            {
                "parameters": [
                    {
                        "name": "a",
                        "documentation": "my parameter documentation",
                        "type": "string"
                    },
                    {
                        "name": "b",
                        "documentation": "another parameter documentation",
                        "type": "C"
                    }
                ],
                "returnType": "C",
                "documentation": "constructor documentation"
            }
        ]
    },
    {
        "name": "D",
        "documentation": "",
        "type": "typeof D",
        "constructors": [
            {
                "parameters": [
                    {
                        "name": "a",
                        "documentation": "my parameter documentation",
                        "type": "string"
                    },
                    {
                        "name": "b",
                        "documentation": "another parameter documentation",
                        "type": "C"
                    }
                ],
                "returnType": "D",
                "documentation": "constructor documentation"
            }
        ]
    }
]

但是我想要这样的东西:

[
    /** C declaration **/
    {
        "name": "D",
        "documentation": "",
        "type": "C", // because extends C
        "parent": "C", // Or like this 
        "constructors": [
            {
                "parameters": [
                    {
                        "name": "a",
                        "documentation": "my parameter documentation",
                        "type": "string"
                    },
                    {
                        "name": "b",
                        "documentation": "another parameter documentation",
                        "type": "C"
                    }
                ],
                "returnType": "D",
                "documentation": "constructor documentation"
            }
        ]
    }
]

我试图找到有关解析打字稿的文档。如果有人有任何链接或想法,那将是非常可观的!

3 个答案:

答案 0 :(得分:0)

编译器API的TypeChecker提供了一种称为getBaseTypeOfLiteralType的方法。返回值是一个Type对象,其中包含symbol: Symbolsymbol依次包含escapedName

checker.getBaseTypeOfLiteralType(constructorType).symbol.escapedName

您可以将其插入所使用代码的serializeClass函数中

function serializeClass(symbol: ts.Symbol) {
    ...
    (<any>details).baseType = checker.getBaseTypeOfLiteralType(constructorType).symbol.escapedName;
    return details;
}

这应该给你这样的输出:

{
    name: 'D',
    type: 'typeof D',
    constructors: [ ... ],
    baseType: 'C'
}

答案 1 :(得分:0)

这是一个用于检索父类的完全限定名称的函数,可以插入该父类以生成“父”值(已通过3.9.5版测试):

function getParentClassFQName(node: ts.ClassDeclaration, checker: ts.TypeChecker): string | undefined {

    if (!node.heritageClauses) {
        return;
    }

    for (let clause of node.heritageClauses) {
        if (clause.token == ts.SyntaxKind.ExtendsKeyword) {
            if (clause.types.length != 1) {
                console.warn('error parsing extends expression "'+clause.getText()+'"');
            } else {
                let symbol = checker.getSymbolAtLocation(clause.types[0].expression);
                if (!symbol) {
                    console.warn('error retrieving symbol for extends expression "'+clause.getText()+'"');
                } else {
                    return checker.getFullyQualifiedName(symbol);
                }
            }
        }
    }

}

其中checker=program.getTypeChecker()和node是通过ts.isClassDeclaration(node)检查的节点。

答案 2 :(得分:0)

这里没有一个解决方案是完美的 - 一个没有返回正确的答案,一个过于复杂。

试试这个:

classType.getBaseTypes()

它返回一个基本类型的数组。我实际上不明白你怎么可能有多个,所以你可能想要检查这种情况并抛出一个错误,这样你就知道它是否发生了:

const getBaseType = (classType) => {
  const baseTypes = classType.getBaseTypes() ?? []

  if (baseTypes.length === 0) {
      throw new Error("No base types.")
  }

  if (baseTypes.length > 1) {
      throw new Error("> 1 base types; not sure which one to pick!")
  }

  return baseTypes[0];
}

如果您需要获取类的类型,请尝试类似

const classType = program.getTypeChecker().getTypeAtLocation(classNode)