ReactJS/TypeScript - Property 'files' does not exist on type 'HTMLElement' error

I am doing a react app with ts and I have this piece of code that returns an error:

  const blobfile = document.getElementById('blobFile');
  if ( blobfile !== null ) {
     const file = blobfile.files[0];
  }

The error is:

Property 'files' does not exist on type 'HTMLElement'

I tried this but does not work:

const file = (<HTMLInputElement>document.getElementById('blobFile')).files[0];

The error for this is:

JSX element type 'HTMLInputElement' is not a constructor function for JSX elements.
  Type 'HTMLInputElement' is missing the following properties from type 'ElementClass': render, context, setState, forceUpdate, and 3 more.ts(2605)
JSX element 'HTMLInputElement' has no corresponding closing tag.ts(17008)

How can I fix this?

Thanks

Upvotes: 2

Views: 3183

Answers (3)

Thank you very much to you, Leon and Michael!

I am using the Leon solution and my code now is:

   onFileChange = (e: React.ChangeEvent<HTMLInputElement>): any => {
      if ( e.target.files == null ) {
         throw new Error("Error finding e.target.files"); 
      }

      return e.target.files[0];
   }

and the button:

<input type="file" onChange={this.onFileChange} />

For better context (I suppose I had to write it in the original post) I am trying to make functional this guide: https://learn.microsoft.com/en-us/archive/blogs/waws/azure-storage-blob-upload-from-browser

Upvotes: 1

Michael
Michael

Reputation: 2454

Your cast doesn't work because you're working with tsx, and therefore the cast is ambiguous (typescript can't tell if you're making a cast, or trying to instantiate a component). Instead you should do casts using the as TypeToCastTo

Eg:

 (document.getElementById('blobFile') as HTMLInputElement).files[0];

There is a tslint rule "no-angle-bracket-type-assertion" that might help with this: https://palantir.github.io/tslint/rules/no-angle-bracket-type-assertion/

In addition, you should take a look at Leon's advice regarding using the change event as this is a better solution than querying the document directly - it is very seldom that you would want to do this.

Upvotes: 0

Leon
Leon

Reputation: 12481

This is a multi parts answer

Part 1.

If you are using React you should have no reason to use getElementById. You should be using the onChange event of the file input

const onFileChange = (e: ChangeEvent<HTMLInputElement>): void => {
    console.log(e.target.files)
}

<input type="file" onChange={onFileChange} />

Part 2

Your type casting is wrong. The idea to type cast is OK, but not strictly correct and getElementById could return null.

const fileElement = document.getElementById('blobFile') as HTMLInputElement
if (fileElement) {
    console.log(fileElement.files)
}

Upvotes: 2

Related Questions