TypeScript Version: 3.7.3
The typescript.SymbolTable is like an ES6 Map -- typescript.d.ts describes it as 'based on the ES6 Map interface'.
However, the underlying interface typescript.UnderscoreEscapedMap does not implement the Map interface, or the Iterable, or Iterator protocols. This means it's not possible to iterate over properly without shim code, which varies from manually implementing the Iterator protocol (annoying!) to overriding the type with as Map<ts.__String, ts.Symbol> (bad!).
Code Example
import * as ts from "typescript";
const p = ts.createProgram(["t.d.ts"], {});
const c = p.getTypeChecker();
p.getSourceFiles().map(f => {
f.forEachChild(n => {
if (!ts.isModuleDeclaration(n)) return;
const s = c.getSymbolAtLocation(n.name);
if (!s) return;
const scanMembers = (s: ts.Symbol) => {
if (s.valueDeclaration === undefined)
console.log("missing valueDeclaration on", s.getName());
type m = Iterator<any>
if (!s.exports) return;
if (!(Symbol.iterator in s.exports))
return console.log("not iterable", s.getName())
for (let [/*name*/, member] of (s.exports as Map<ts.__String, ts.Symbol>)) {
scanMembers(member);
}
}
scanMembers(s);
})
})
typescript.UnderscoreEscapedMap is not recognized as a Map due to clear(), delete(), set(), [Symbol.toStringTag] and [Symbol.iterator] being undefined.
Testing map assertion
// Type 'ReadonlyUnderscoreEscapedMap<any>' is missing the following properties
// from type 'Map<any, any>': clear, delete, set, [Symbol.iterator],
// [Symbol.toStringTag] ts(2739)
const x: Map<any, any> = void 0 as any as ts.ReadonlyUnderscoreEscapedMap<any>
Perhaps this is a compiler internals issue, as using as Map<ts.__String, ts.Symbol> makes SymbolTables work without issue. If it's not, the fix should be as simple as replacing typescript.UnderscoreEscapedMap with Map and typescript.ReadonlyUnderscoreEscapedMap with ReadonlyMap.
Search Terms:
Code
import * as ts from "typescript";
const p = ts.createProgram(["t.d.ts"], {});
const c = p.getTypeChecker();
p.getSourceFiles().map(f => {
f.forEachChild(n => {
if (!ts.isModuleDeclaration(n)) return;
const s = c.getSymbolAtLocation(n.name);
if (!s) return;
const scanMembers = (s: ts.Symbol) => {
if (s.valueDeclaration === undefined)
console.log("missing valueDeclaration on", s.getName());
type m = Iterator<any>
if (!s.exports) return;
if (!(Symbol.iterator in s.exports))
return console.log("not iterable", s.getName())
// error!!
for (let [/*name*/, member] of s.exports) {
scanMembers(member);
}
}
scanMembers(s);
})
})
Expected behavior:
It should be possible to iterate over a typescript.SymbolTable.
Actual behavior:
typescript.SymbolTable is considered not iterable.
TypeScript Version: 3.7.3
The
typescript.SymbolTableis like an ES6Map-- typescript.d.ts describes it as 'based on the ES6 Map interface'.However, the underlying interface
typescript.UnderscoreEscapedMapdoes not implement theMapinterface, or theIterable, orIteratorprotocols. This means it's not possible to iterate over properly without shim code, which varies from manually implementing the Iterator protocol (annoying!) to overriding the type withas Map<ts.__String, ts.Symbol>(bad!).Code Example
typescript.UnderscoreEscapedMapis not recognized as aMapdue toclear(),delete(),set(),[Symbol.toStringTag]and[Symbol.iterator]beingundefined.Testing map assertion
Perhaps this is a compiler internals issue, as using
as Map<ts.__String, ts.Symbol>makesSymbolTables work without issue. If it's not, the fix should be as simple as replacingtypescript.UnderscoreEscapedMapwithMapandtypescript.ReadonlyUnderscoreEscapedMapwithReadonlyMap.Search Terms:
Code
Expected behavior:
It should be possible to iterate over a
typescript.SymbolTable.Actual behavior:
typescript.SymbolTableis considered not iterable.