Skip to content

Instantly share code, notes, and snippets.

@surma
Last active January 21, 2025 12:46
Show Gist options
  • Save surma/be14ca81065bf227cee785870ee8a993 to your computer and use it in GitHub Desktop.
Save surma/be14ca81065bf227cee785870ee8a993 to your computer and use it in GitHub Desktop.
import * as ts from "typescript";
const compilerOptions = {
target: ts.ScriptTarget.Latest,
module: ts.ModuleKind.ESNext,
strict: true,
noEmit: true,
lib: [],
types: [],
};
const code = `
class A;
function x<T>(a: T) {
return "x";
}
function main() {
// Here type parameter T is bound to type A.
// I want to extract that information.
x(new A());
}
`;
const host = ts.createCompilerHost(compilerOptions);
host.getSourceFile = (fileName) => {
if (fileName === "test.ts") {
return ts.createSourceFile(fileName, code, ts.ScriptTarget.Latest);
}
return undefined;
};
const program = ts.createProgram(["test.ts"], compilerOptions, host);
const typeChecker = program.getTypeChecker();
const sourceFile = program.getSourceFile("test.ts");
function visit(node) {
if (node.kind == ts.SyntaxKind.CallExpression) {
const sig = typeChecker.getResolvedSignature(node);
// Assert the function has type parameters
console.assert(sig.declaration.typeParameters.length == 1);
// I know the data I want is in `sig.mapper`, but that’s not a public API.
// `typeParameters` is `undefined`
console.log(sig.typeParameters);
// `getTypeArguments` returns the empty array for `sig`, `node`, `node.expression`, etc
const typeArg = typeChecker.getTypeArguments(sig);
console.log({ typeArg });
// What is the right API call here?
}
ts.forEachChild(node, visit);
}
visit(sourceFile);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment