Repository: TypeScript
Issue: `typescript.SymbolTable` does not properly implement the ES6 Map interface
Labels: Suggestion,API,Awaiting More Feedback

<!-- 🚨 STOP 🚨 𝗦𝗧𝗢𝗣 🚨 𝑺𝑻𝑶𝑷 🚨

Half of all issues filed here are duplicates, answered in the FAQ, or not appropriate for the bug tracker. Even if you think you've found a *bug*, please read the FAQ first, especially the Common "Bugs" That Aren't Bugs section!

Please help us by doing the following steps before logging an issue:
  * Search: https://github.com/Microsoft/TypeScript/search?type=Issues
  * Read the FAQ: https://github.com/Microsoft/TypeScript/wiki/FAQ

Please fill in the *entire* template below.
-->

<!--
Please try to reproduce the issue with the latest published version. It may have already been fixed.
For npm: `typescript@next`
This is also the 'Nightly' version in the playground: http://www.typescriptlang.org/play/?ts=Nightly
-->
**TypeScript Version:**  3.7.3

The [`typescript.SymbolTable`] is like an ES6 `Map` -- typescript.d.ts [describes it](https://github.com/microsoft/TypeScript/blob/master/lib/typescript.d.ts#L2317) 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!).

<details>
<summary>Code Example</summary>

```typescript
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);


    })
})
```
</details>

`typescript.UnderscoreEscapedMap` is not recognized as a `Map` due to `clear()`, `delete()`, `set()`, `[Symbol.toStringTag]` and `[Symbol.iterator]` being `undefined.`

<details>
<summary>Testing map assertion</summary>

```typescript
// 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>
```
</details>

Perhaps this is a compiler internals issue, as using `as Map<ts.__String, ts.Symbol>` makes `SymbolTable`s work without issue. If it's not, the fix should be as simple as replacing [`typescript.UnderscoreEscapedMap`] with `Map` and [`typescript.ReadonlyUnderscoreEscapedMap`] with `ReadonlyMap`.

[`typescript.ReadonlyUnderscoreEscapedMap`]: https://github.com/microsoft/TypeScript/blob/master/lib/typescript.d.ts#L2302
[`typescript.UnderscoreEscapedMap`]: https://github.com/microsoft/TypeScript/blob/master/lib/typescript.d.ts#L2312
[`typescript.SymbolTable`]: https://github.com/microsoft/TypeScript/blob/master/lib/typescript.d.ts#L2318
[`Map`]: https://github.com/microsoft/TypeScript/blob/master/lib/lib.es2015.collection.d.ts#L21
[`Iterable`]: https://github.com/microsoft/TypeScript/blob/master/lib/lib.es2015.iterable.d.ts#L50
[`Iterator`]: https://github.com/microsoft/TypeScript/blob/master/lib/lib.es2015.iterable.d.ts#L43

<!-- Search terms you tried before logging this (so others can find this issue more easily) -->
**Search Terms:**

**Code**

```ts
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.