2 ms·
Just type (… as HTMLInputElement) and be done with it. It’s really not that hard.
by explaininjs 3y ago
Just type (… as HTMLInputElement) and be done with it. It’s really not that hard.
- jdthedisciple 3y agoDuh, that's what I did. And every other variant one can possibly think of. To no avail. That's what cost me the hour or two. This works like a charm in a strictly typed language like C#, but TypeScript just hasn't got it down correctly yet.
- explaininjs 3y agoShow a sample of the issue if you can.
- jdthedisciple 3y agoThe code in question: (e: Event) => { let t: EventTarget | null = e.target; // here "t as HTMLInputElement" did not work if (t instanceof HTMLInputElement && t.files && t.files[0]) { const file = t.files[0]; if (file) { (myImageElem! as HTMLImageElement).src = URL.createObjectURL(file); } } } TS wouldn't accept it. My guess is it's not cluttered enough. My final vanilla version OTOH: (e) => { const t = e.target; if (t.files) { const file = t.files[0]; myImageElem.src = URL.createObjectURL(file); } } How is the latter not a million times more elegant? Why do I need to clutter everything with types that I won't even think twice about?
- SebastianKra 3y agoThat second version is literally 100% verified and valid Typescript. `e` is inferred from `HTMLProps<HTMLInputElement>['onChange']` `t` is inferred from `e` `files` is inferred from `t` No halfway experienced TS developer would write any of these annotations. If you got the myImageElem from a ref, you may need to add a !, because yes, it's not technically guaranteed that the ref is set by the time the callback is called.
- Dylan16807 3y agoWell I haven't ever used next.js in particular, but if I go open a .tsx file and add <input type="file" onChange={[final vanilla version code]} />, it works fine. t gets inferred as `EventTarget & HTMLInputElement` The only error is that "myImageElem" isn't defined by the snippet, which is to be expected. If I insert your first snippet, it complains that (e:Event) isn't the right type, but (e) or (e:any) makes the whole thing happy (except "myImageElem"). If I remove the imprecise "Event" typing on e, then your first snippet can be simplified to: let t = e.target; if (t.files && t.files[0]) { If I keep (e: Event), then the code with "instanceof" works, as does: let t = e.target as HTMLInputElement; if (t.files && t.files[0]) {
- jdthedisciple 3y ago> The only error is that "myImageElem" isn't defined by the snippet, which is to be expected. It's the ID of a DOM element. No need to define it (for me). But anyway still good I will try your code, thanks.
- Dylan16807 3y agoIn that case the only thing you need to make your vanilla code work as typescript is to put the following somewhere: declare var myImageElem: HTMLImageElement;
- consilient 3y ago`(e: Event) =>` means you accept any event whatsoever.
- jdthedisciple 3y agoThat is probably true, however as I said it should (IMO) still work if I then cast its target to HTMLInputElement.