Is there an event type for the HTMLInputElement change event? Currently is automatically resolved as general Event
> EventTarget
. Which has no files
property. see FileList
.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement
Example:
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.addEventListener('change', (event: Event) => {
handleFileLoad(event.target.files); // Error: files does not exist on EventTarget.
});
document.body.appendChild(this.fileInput);
tsconfig.json (typescript 3.4.5):
{
"compilerOptions": {
"outDir": "./dist/",
"noImplicitAny": true,
"sourceMap": true,
"module": "esnext",
"target": "es5",
"moduleResolution": "node",
"strict": true
},
"exclude": ["node_modules", "dist"]
}
If not, this is a feature request. :) e.g.
As per this Stackoverflow answer, you can cast event.target
as HTMLInputElement
to get around this.
document.getElementById("customimage").onchange= function(e: Event) {
let file = (<HTMLInputElement>e.target).files[0];
//rest of your code...
}
I suggest extending EventTarget for optional property files.
For those that come behind, I liked this solution:
export type FileEventTarget = EventTarget & { files: FileList };
const fileInputNativeElement =
fromEvent(fileInputNativeElement, 'change') as Observable<{ target: FileEventTarget }>;
I always wondered why Event
is not generic.
interface Event<T = EventTarget> {
target: T;
// ...
}
So we define the type where we need it.
function myEventListener(event: Event<HTMLInputElement>) {
console.log(event.target.files);
}
function otherEventListener(event: Event<HTMLAnchorElement>) {
console.log(event.target.href);
}
This can be made backwards compatible with default generics:
// still works
function myEventListener(event: Event) {}
Don't put the type of event :)
I'm working with TypeScript ~3.8.3
and HTMLInputElement
contains now files
(FileList
).
const target = event.target as HTMLInputElement;
const files = target.files;
I'm working with TypeScript
~3.8.3
andHTMLInputElement
contains nowfiles
(FileList
).const target = event.target as HTMLInputElement; const files = target.files;
I was have the same problem and it worked when I quit use the type of element. Thank you for answer me.
That's correct. It also exists in TypeScript 3.4.5. It also exists in the old version TypeScript 2.0
I don't know what I was thinking back then. ... 🤦♂️
I close this issue as fixed. Thanks. The type HTMLInputElement
has the property files
which is nullable FileList
. All fine.
const target = event.target as HTMLInputElement;
const files = target.files;
I understood the issue as event.target
doesn't have files and that's because it requires casting.
We could take this opportunity to remove the casting step using generics
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.addEventListener('change', event => {
console.log(event.target.files);
});
This is acual resolved by the TypeScript in VS Code. (just hover the method to see it.)
HTMLInputElement.addEventListener<"change">(
type: "change",
listener: (this: HTMLInputElement, ev: Event) => any,
options?: boolean | AddEventListenerOptions
): void
Means that the HTMLInputElement is detected and maybe available for a generic event type. 🤔
Is there already a generic Event
type? But anyway it is not resolved in this generic type.
It's a good idea. If TypeScript detects the context of the event listener - in this case - why not?
But note that in my initial post, I use the fixed type Event
for the event
variable.
So the Event
type of a addEventListener
should detect the target type (generic) if possible.
Any examples or ideas? Any expertise of a member or constributor?
the issue with making target
generic here is related to bubbling events. Adding a listener somewhere will generally not guarantee you the type of target
as it can actually be dispatched on a child node. For instance, clicking on a button might actually click on an icon inside that button instead.
As per this Stackoverflow answer, you can cast
event.target
asHTMLInputElement
to get around this.document.getElementById("customimage").onchange= function(e: Event) { let file = (<HTMLInputElement>e.target).files[0]; //rest of your code... }
let files:FileList = (<FileList>(<HTMLInputElement>e.target).files);
console.log(files.item(0));
Most helpful comment
I always wondered why
Event
is not generic.So we define the type where we need it.
This can be made backwards compatible with default generics: