首页 > 解决方案 > 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]

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

我想使用Compiler API做同样的事情。我有program.typeChecker,我被困在这里。我怎么能得到隐式类型参数?

标签: typescripttypescript-compiler-api

解决方案


Testinextends Test的类型M不是隐式类型为Test<number, boolean>. 该类M覆盖了testto be的声明test(q: number): boolean。如果你得到它的类型,ExpressionWithTypeArguemnts它将是.extends TestMTest<unknown, unknown>

从获取类型M

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

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

...并且您想找到参数的类型和返回类型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));

给定,Test发现PRM

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

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

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

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


推荐阅读