Skip to content

instanceof a Map/Set SUBCLASS is false (m instanceof MyMap); only the native base edge survives #7575

Description

@proggeramlug

m instanceof MyMap is false for a class MyMap extends Map instance.
m instanceof Map is correct. Found while fixing #7570 (PR #7573); it is a
different bug and survives that fix — it reproduces with and without the
base-type annotation, so it is not a declared-type-lowering problem.

Repro

class MyMap<K, V> extends Map<K, V> {}
class Plain {}
class SubPlain extends Plain {}

const a = new MyMap<string, number>();
console.log("unannotated:", a instanceof MyMap, a instanceof Map);

const b: Map<string, number> = new MyMap<string, number>();
console.log("annotated:", b instanceof MyMap, b instanceof Map);

// control: an ordinary class hierarchy is fine
const c: Plain = new SubPlain();
console.log("plain annotated:", c instanceof SubPlain, c instanceof Plain);
$ node --experimental-strip-types inst.ts
unannotated: true true
annotated: true true
plain annotated: true true

$ ./inst
unannotated: false true          <-- both wrong
annotated: false true
plain annotated: true true       <-- ordinary classes are fine

So the intermediate/leaf class edge is what is lost, not the base edge: the
chain walk finds Map but not MyMap. The same holds for class MySet extends Set.

Notes for whoever picks this up

  • Ordinary (non-native-base) inheritance is unaffected, so this is specific to
    the super()-to-a-native-base wiring, not to instanceof in general.
    CLAUDE.md's Known-weak areas entry on native base-class subclassing is the
    right place to start: "a native base's surface is installed at super() time
    and its parent edge lives in the class registry".
  • The existing test_gap_6325_map_set_subclass.ts only asserts
    m instanceof Map, which is why this was never caught.
  • test_gap_7570_map_set_declared_base_type.ts deliberately asserts only
    instanceof Map / instanceof Set, with an inline comment pointing here.
    Whoever fixes this should tighten those two lines to also assert
    instanceof MyMap / instanceof MySet.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions