Skip to content

Missing string indexer on NamedNodeMap interface in lib.dom.d.ts? #30928

Description

For context, see refined-github/refined-github#1783, specifically this commit, refined-github/refined-github@48baae0.

Also, just posting my tweet about this so that people can find discussions about the issue. See https://twitter.com/nickytonline/status/1117524648982392833

I'll restate what I tweeted as I probably should have posted my question here originally.

The NamedNodeMap interface in lib.dom.ts does not allow for a string indexer, even though vanilla JS supports this in browsers, e.g. someDomElement.attribute['aria-label'].value.

We have code like this in the Refined GitHub extension, so for the time being, I've gone ahead via a declaration merge for NamedNodeMap

interface NamedNodeMap {
      [key: string]: Attr;
}

I can't tell from the MDN docs for NamedNodeMap if it's standard or not. All they seem to mention is "Attr nodes' indexes may differ among browsers" which wouldn't apply to access by the attribute name.

Just wondering if this was omitted by mistake or is it because this is not considered WHATWG DOM standard? I went to https://dom.spec.whatwg.org/#interface-namednodemap and unless I'm reading it incorrectly, I believe it states that using a string indexer is valid.

Thoughts? Happy to PR this up if it's valid.

Activity

  1. changed the title [-]Missing string indexer on NamedNodeMap?[/-] [+]Missing string indexer on NamedNodeMap interface in lib.dom.d.ts?[/+] on Apr 15, 2019
  2. Jessidhia commented on Apr 17, 2019

    @Jessidhia

    There are two indices specified; a numeric and a string index:

    "NamedNodeMap object’s supported property indices are the numbers in the range zero to its attribute list’s size minus one, unless the attribute list is empty, in which case there are no supported property indices."

    This is the numeric index; typical ArrayLike<Attr>.

    "A NamedNodeMap object’s supported property names are the return value of running these steps:

    1. Let names be the qualified names of the attributes in this NamedNodeMap object’s attribute list, with duplicates omitted, in order.
    2. If this NamedNodeMap object’s element is in the HTML namespace and its node document is an HTML document, then for each name in names:
      1. Let lowercaseName be name, in ASCII lowercase.
      2. If lowercaseName is not equal to name, remove name from names.
    3. Return names."

    This is the named string index. It's case-sensitive in SVG documents/elements, forced-lowercase in HTML documents.

    We can't represent this in typescript, but only the numeric indices are enumerable. Any string index is enumerable: false. This also means that Object.values would use the wrong overload! Fortunately both indices (where defined) have Attr instances.

  3. saschanaz commented on Apr 26, 2019

    @saschanaz
    Contributor

    AFAIK this is intentionally disabled because TS didn't support string indexer when any other member has a different type than the indexer returns. But looks like somehow that behavior changed. Still causes errors when creating new types.

  4. trusktr commented on Dec 28, 2019

    @trusktr
    Contributor

    I ran into this today porting some old code relying on the format element.attributes[name].value.

    Maybe the string index should actually be

    interface NamedNodeMap {
          [key: string]: Attr | undefined;
    }

    ? Otherwise it will thing every access of any string results in Attr, which isn't the case. Should this be applied to number indices too?

  5. added
    Design LimitationConstraints of the existing architecture prevent this from being fixed
    and removed
    BugA bug in TypeScript
    Domain: lib.d.tsThe issue relates to the different libraries shipped with TypeScript
    on Aug 25, 2026
  6. RyanCavanaugh commented on Aug 25, 2026

    @RyanCavanaugh
    Member

    We can't add an illegal string indexer, since this interface has other members that aren't Attr (e.g. x.setNamedItem). We'd need support for "rest" object signatures, which doesn't exist yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions