Repro
In self-hosted code (src/semantic/type-annotator.ts during work on #651):
```ts
const top: Map<string, ResolvedType> | null =
this.scopeStack.length > 0 ? this.scopeStack[this.scopeStack.length - 1] : null;
if (top) top.set(name, type);
```
Stage 0 build (node compiler compiling chad-native) errors:
```
error: Method 'set' on 'top' is not supported.
```
Workaround
Hoist the length check outside, avoid the union:
```ts
if (this.scopeStack.length === 0) return;
const top = this.scopeStack[this.scopeStack.length - 1];
top.set(name, type);
```
compiles fine.
Root cause (suspected)
Ternary + null branch creates `Map | null` union. Method dispatch on the union can't pick the Map branch even inside an `if (top)` narrow. Separate `nullable` tracking that doesn't flow into union → intersection.
Impact
Forces awkward control-flow refactors in new self-hosted code. Common TS pattern should just work.
cc #640 (ergonomic block for sema work)
Repro
In self-hosted code (src/semantic/type-annotator.ts during work on #651):
```ts
const top: Map<string, ResolvedType> | null =
this.scopeStack.length > 0 ? this.scopeStack[this.scopeStack.length - 1] : null;
if (top) top.set(name, type);
```
Stage 0 build (node compiler compiling chad-native) errors:
```
error: Method 'set' on 'top' is not supported.
```
Workaround
Hoist the length check outside, avoid the union:
```ts
if (this.scopeStack.length === 0) return;
const top = this.scopeStack[this.scopeStack.length - 1];
top.set(name, type);
```
compiles fine.
Root cause (suspected)
Ternary + null branch creates `Map | null` union. Method dispatch on the union can't pick the Map branch even inside an `if (top)` narrow. Separate `nullable` tracking that doesn't flow into union → intersection.
Impact
Forces awkward control-flow refactors in new self-hosted code. Common TS pattern should just work.
cc #640 (ergonomic block for sema work)