Type 'HTMLFormControlsCollection' has no property 'x' and no string index signature

1k views Asked by At

The following error appears when trying to destructure a form.elements object:

Type 'HTMLFormControlsCollection' has no property 'x' and no string index signature

// in a class

domRefs: {[key: string]: HTMLFormElement | null} = {
  myForm: null
}

onButtonClick = () => {
  console.debug(this.domRefs.myForm!.elements) // screenshot below
  const {a, b, c} = this.domRefs.myForm!.elements
}

screenshot of the console output

I don't want to use the : any type annotation that does not emit this error.

2

There are 2 answers

6
Oleg Valter is with Ukraine On

This is a limitation of the standard DOM definitions library (and still is in 2021). Here is how the HTMLFormControlsCollection is defined in it - notice the lack of a string index signature (this is exactly why the error happens):

interface HTMLFormControlsCollection extends HTMLCollectionBase {
    /**
     * Returns the item with ID or name name from the collection.
     * 
     * If there are multiple matching items, then a RadioNodeList object containing all those elements is returned.
     */
    namedItem(name: string): RadioNodeList | Element | null;
}

Its parent interface HTMLCollectionBase also lacks a string index signature (despite having a number index signature):

interface HTMLCollectionBase {
    /**
     * Sets or retrieves the number of objects in a collection.
     */
    readonly length: number;
    /**
     * Retrieves an object from various collections.
     */
    item(index: number): Element | null;
    [index: number]: Element;
}

However, HTMLFormControlsCollection should have a string index signature by definition (see the standard):

element = collection[name]
radioNodeList = collection[name]
Returns the item with ID or name name from the collection.

So, with the help of some declaration merging, we can fix the omission:

interface HTMLFormControlsCollection extends HTMLCollectionBase {
  [item: string]: Element | RadioNodeList;
}
2
Karan Badhwar On

As described by @oleg-valter-is-with-ukraine,

interface HTMLFormControlsCollection extends HTMLCollectionBase {
  [item: string]: HTMLInputElement | RadioNodeList;
}

It worked for me I just changed the Element to HTMLInputElement in the lib.dom.d.ts file