Typescript 使用编译器 API 推断类型参数

Ale*_*Ten 5 typescript typescript-compiler-api

使用此代码(游乐场):

declare class Test<P = unknown, R = unknown> {
    test(p: P): R;
}

declare class M extends Test {
    test(q: number): boolean;
}

// these lines are not in real code. This is an example of what TS
// could infer from my code and what I would like to find using Compiler API
type Sgn<M> = M extends Test<infer P, infer R> ? [P, R] : never;
type sgn = Sgn<M>; // [number, boolean]
Run Code Online (Sandbox Code Playgroud)

typescript 可以从类声明中的方法推断出类M( P = number, R = boolean)的隐式类型参数test。

我想使用Compiler API做同样的事情。我已经被program.typeChecker困在这里了。我怎样才能获得隐式类型参数?

Dav*_*ret 3

ofTest中的类型未隐式键入为。该类覆盖了to be的声明。如果你得到的类型将会是.extends TestMTest<number, boolean>Mtesttest(q: number): booleanExpressionWithTypeArguemntsextends TestMTest<unknown, unknown>

从以下位置获取类型M

如果你知道 的结构Test是什么并且你...

declare class M extends Test {
    test(q: number): boolean;
}
Run Code Online (Sandbox Code Playgroud)

...并且你想找到参数的类型和返回类型test,那么你可以执行以下操作:

const mDecl = sourceFile.statements.find(child =>
    ts.isClassDeclaration(child) && child.name?.escapedText === "M"
)! as ts.ClassDeclaration;
const testMethod = mDecl.members.find(member =>
    ts.isMethodDeclaration(member)
    && ts.isIdentifier(member.name)
    && member.name.escapedText === "test"
)! as ts.MethodDeclaration;

// number type
typeChecker.getTypeAtLocation(testMethod.parameters[0]);
// boolean type
typeChecker.getReturnTypeOfSignature(typeChecker.getSignatureFromDeclaration(testMethod));
Run Code Online (Sandbox Code Playgroud)

给定Test, 求P和R中M

如果您已经Test找到并且想要查找Pand RinM并且您不知道 的类型Test可能是什么样子,那么您不能使用前面描述的方法。

为此,您将必须Test手动遍历 的类型,然后以相同的方式遍历并查看 中使用的M类型参数是什么类型。这样做有点复杂,并且在此处发布的工作/代码太多。TestM

基本上,没有简单的方法来构建类型然后与编译器 API 进行比较。有一些建议可以使这变得更容易(例如Type Builder API Proposal和Type Relationship API Proposal)。

也就是说,解决这个问题的一种方法是通过创建一个虚拟文件ts.createSourceFile并在其中写入一些代码(例如您的Sgn和sgn声明),然后使用该文件上的类型检查器来解析类型。