Symbol resolution
- TypeScript course
- Expert
- Lesson 10/35
- 4 min
Learn declaration resolution with Symbol.
Symbol resolution
Symbol resolution is finding which declaration an identifier refers to. checker.getSymbolAtLocation(node) returns a Symbol | undefined for an Identifier node. The symbol carries the declaration's name and its declaration list.
const sym = checker.getSymbolAtLocation(id);
if (sym) {
console.log(sym.getName());
console.log(sym.declarations?.length);
}Symbol and declarations
A symbol's .declarations property is an array of all declarations of that symbol. Most cases have a single declaration, but function overloads can have several. symbol.getName() returns the declaration's name.
const sym = checker.getSymbolAtLocation(node.name);
console.log(sym?.declarations?.length); // 1
console.log(sym?.getName()); // "topla"Practice Resolve the function symbol
Create an in-memory program from function topla(a: number, b: number): number { return a + b; } with noLib: true. Obtain the TypeChecker, write a visit function that resolves the symbol of each FunctionDeclaration's name with getSymbolAtLocation and prints name: declarationCount. Walk with ts.forEachChild.
Starter code
import * as ts from "typescript";
// Kaynak: function topla(a: number, b: number): number { return a + b; }
// host ve program oluştur (noLib: true)
// TypeChecker al
// visit fonksiyonu yaz: FunctionDeclaration bulunca sembolünü çöz
// ad: tanımSayisi biçiminde yazdır
// forEachChild ile gez
// kodunu buraya yazSample solution
import ts from "typescript";
const fileName = "app.ts";
const sourceText = "function topla(a: number, b: number): number { return a + b; }";
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)!;
function visit(node: ts.Node) {
if (ts.isFunctionDeclaration(node) && node.name) {
const sym = checker.getSymbolAtLocation(node.name);
console.log(`${sym?.getName()}: ${sym?.declarations?.length}`);
}
ts.forEachChild(node, visit);
}
visit(sf);Expected output
topla: 1
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What does checker.getSymbolAtLocation(id) return?
- string
- Type
- Symbol | undefined Correct answer
- Declaration[]
Explanation: getSymbolAtLocation returns Symbol | undefined for an Identifier; undefined when there is no declaration. It does not directly return a string, Type or Declaration[].
2 Declaration count
const sym = checker.getSymbolAtLocation(node.name);
console.log(sym?.____?.length);
const sym = checker.getSymbolAtLocation(node.name);
console.log(sym?.declarations?.length);
Explanation: Symbol.declarations returns a Declaration[]; there is no getDeclarations method, declarationList is specific to VariableDeclaration, and nodes is not a general property.
3 Symbol resolution parts
| Term | Meaning |
|---|---|
checker.getSymbolAtLocation |
Gives Symbol for an Identifier |
symbol.getName() |
Returns the declaration name |
symbol.declarations |
Gives the declaration array |
TypeChecker |
Resolves symbols and types |