TypeScript编译器API:获取通用方法的已解析返回类型

问题描述

假设我们有一个通用类或接口:

interface A<T> {
    prop1: T;
    func2(): T;
}

interface B extends A<C> {
}


interface C {
}

我们需要获取B.func2方法的返回类型(不是T而是C)。

here所描述的方式对道具有效,但我不知道如何为方法进行修改

for (const statement of sourceFile.statements) {

    if (!isInterface(statement))
        continue;

    if (!statement.heritageClauses?.length)
        continue;

    for (const heritageClause of statement.heritageClauses) {

        for (const exprWithTypeArgs of heritageClause.types) {
            const baseType = checker.getTypeAtLocation(exprWithTypeArgs);

            for (const propSymbol of baseType.getProperties()) {
                const resolvedType = checker.getTypeOfSymbolAtLocation(propSymbol,exprWithTypeArgs);

                console.log(`${propSymbol.name} has type: ${resolvedType.symbol?.name}`);
                // prints
                // prop1 has type: C
                // func2 has type: func1

                for (const propDeclaration of propSymbol.declarations) {
                    if (!isSignatureDeclaration(propDeclaration))
                        continue;

                    const signature = checker.getSignatureFromDeclaration(propDeclaration);
                    const returnTypeSymbol = checker.getReturnTypeOfSignature(signature)?.symbol;
                    const resolvedReturnType = checker.getTypeOfSymbolAtLocation(returnTypeSymbol,exprWithTypeArgs);

                    console.log(`${propSymbol.name} return type: ${resolvedReturnType.symbol?.name}`);
                    // prints
                    // func2 return type: undefined
                }
            }
        }
    }
}

获取方法的返回类型的正确方法是什么?

解决方法

TypeChecker#getSignaturesOfType方法允许获取类型的签名。

const bDecl = sourceFile.statements[1]; // obviously,improve this
const bType = typeChecker.getTypeAtLocation(bDecl);
const func2Symbol = bType.getProperty("func2")!;
const func2Type = typeChecker.getTypeOfSymbolAtLocation(func2Symbol,func2Symbol.valueDeclaration);
const func2Signature = checker.getSignaturesOfType(func2Type,ts.SignatureKind.Call)[0];

checker.typeToString(func2Signature.getReturnType()); // C