CodeBlanks Logo Icon CodeBlanks

TypeChecker

Learn symbol and type resolution with TypeChecker.

What is the TypeChecker?

The TypeChecker is the symbol and type resolver produced by the Program. You obtain it with program.getTypeChecker(). For a node, you fetch its symbol with getSymbolAtLocation and its type with getTypeAtLocation.

const program = ts.createProgram(["app.ts"], {}, host);
const checker = program.getTypeChecker();

const sym = checker.getSymbolAtLocation(node);
const type = checker.getTypeAtLocation(node);

Without the TypeChecker the AST is pure syntax — it has no meaning.

Symbol and Type

A Symbol represents a declaration — a variable, function or class. symbol.getName() returns the declaration's name. A Type carries type information; for a human-readable form you use checker.typeToString(type).

const sym = checker.getSymbolAtLocation(id);
console.log(sym?.getName()); // "greeting"

const t = checker.getTypeAtLocation(id);
console.log(checker.typeToString(t)); // "string"

Practice Resolve the symbol and print its name

Let the in-memory app.ts source be let greeting = 'merhaba';. Define a CompilerHost, build the program with noLib: true. Obtain the TypeChecker, resolve the symbol of the greeting identifier with getSymbolAtLocation and print its name with getName().

Starter code

index.ts
import * as ts from "typescript";

// Kaynak: let greeting = 'merhaba';
// host'u tanımla (noLib: true ile)
// TypeChecker al
// greeting tanımlayıcısını bul, sembolünü çöz ve adını yazdır

// kodunu buraya yaz

Sample solution

index.ts
import ts from "typescript";

const fileName = "app.ts";
const sourceText = "let greeting = 'merhaba';";

const host: ts.CompilerHost = {
  fileExists: (n) => n === fileName,
  readFile: (n) => (n === fileName ? sourceText : undefined),
  getSourceFile: (n, lang) =>
    n === fileName ? ts.createSourceFile(n, sourceText, lang, true) : undefined,
  writeFile: () => {},
  getDefaultLibFileName: () => "lib.d.ts",
  useCaseSensitiveFileNames: () => true,
  getCanonicalFileName: (n) => n,
  getCurrentDirectory: () => "",
  getNewLine: () => "\n",
};

const program = ts.createProgram([fileName], { noLib: true }, host);
const checker = program.getTypeChecker();
const sf = program.getSourceFile(fileName)!;
const stmt = sf.statements[0] as ts.VariableStatement;
const id = stmt.declarationList.declarations[0].name as ts.Identifier;
const sym = checker.getSymbolAtLocation(id);
console.log(sym?.getName());

Expected output

greeting

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 How is the TypeChecker obtained?

  • program.getChecker()
  • checker.from(program)
  • ts.createChecker(program)
  • program.getTypeChecker() Correct answer

Explanation: The TypeChecker is obtained via program.getTypeChecker(); it returns the symbol and type resolver. The other names do not exist on Program.

2 Symbol's name

Question
const checker = program.getTypeChecker();
const decl = (sf.statements[0] as ts.VariableStatement).declarationList.declarations[0];
const sym = checker.getSymbolAtLocation(decl.name);
console.log(sym?.____());
Answer
const checker = program.getTypeChecker();
const decl = (sf.statements[0] as ts.VariableStatement).declarationList.declarations[0];
const sym = checker.getSymbolAtLocation(decl.name);
console.log(sym?.getName());

Explanation: Symbol.getName() returns the declaration name of the symbol; getType and getId do not exist on Symbol and toString gives the default object representation.

3 TypeChecker parts

Term Meaning
program.getTypeChecker() Returns the TypeChecker
getSymbolAtLocation(node) Returns Symbol | undefined
getTypeAtLocation(node) Returns a Type
symbol.getName() Gives the declaration's name

All lessons in Expert