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

Typescript Infer type params with Compiler API

使用此代码 (playground):

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 可以从 class 声明中的方法 test 推断出 class MP = numberR = boolean)的隐式类型参数。

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

Mextends Test 中的类型 Test 未隐式类型化为 Test<number, boolean>。 class Mtest 的声明覆盖为 test(q: number): boolean。如果您在 Mextends Test 中得到 ExpressionWithTypeArguemnts 的类型,它将是 Test<unknown, unknown>.

M

获取类型

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

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

...而你想找到参数的类型和test的return类型,那么你可以这样做:

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,在 M

中找到 PR

如果您有 Test 并且想在 M 中查找 PR 并且您不知道 Test 的类型可能长得像,那你就不能用前面介绍的方法了

要做到这一点,就得手动遍历Test的类型,然后用同样的方法遍历M,看看Test中的类型参数用的是什么类型在 M。这样做有点复杂,这里 work/code 到 post 太多了。

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

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