Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request to change currentTarget in Event interface for lib.d.ts #299

Open
nathggns opened this issue Jul 29, 2014 · 39 comments · May be fixed by microsoft/TypeScript-DOM-lib-generator#1624
Labels
Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Help Wanted You can do this Suggestion An idea for TypeScript
Milestone

Comments

@nathggns
Copy link

When using the Event interface from lib.d.ts, and attaching a listener, the callback will get an object of type Event. However, the Event's currentTarget property is of type EventTarget (whereas it's should be of type Element/HTMLElement).

@saschanaz
Copy link
Contributor

XMLHttpRequest object also can be currentTarget but it is not Element/HTMLElement. Maybe that's the reason behind this. Would generic type improve this?

interface Event<T extends EventTarget> {
    /* ... */
    currentTarget: T;
    /* ... */
}

interface EventListener<T extends EventTarget> {
    (evt: Event<T>): void;
}

interface HTMLElement {
    /* ... */
    addEventListener(type: string, listener: EventListener<HTMLElement>, useCapture?: boolean): void;
}

@nathggns
Copy link
Author

nathggns commented Aug 3, 2014

Looks like it'll go a long way to improving it.

Sent from my iPhone

On 3 Aug 2014, at 13:34, SaschaNaz [email protected] wrote:

XMLHttpRequest object also can be currentTarget but it is not Element/HTMLElement. Maybe that's the reason behind this. Would generic type improve this?

interface Event {
/* ... /
currentTarget: T;
/
... */
}

interface EventListener {
(evt: Event): void;
}

interface HTMLElement {
/* ... */
addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
}

Reply to this email directly or view it on GitHub.

@RyanCavanaugh
Copy link
Member

Note that not every event target is an Element (http://www.w3.org/TR/DOM-Level-3-Events/#event-types), so the solution here would have to be more along the lines of @saschanaz's suggestion.

The problem is that we currently generate lib.d.ts, using a script, based on a file which we can't make public at this time, and that file is being deprecated in favor of a new one. Because of that, we're not going to make improvements in the script at this time, but hopefully in the future we can take PRs on the lib.d.ts generation script/input.

Tagging 'Revisit' for now - please ping us on this in a month and I can see where we're at.

@saschanaz
Copy link
Contributor

Is there any syntax to refer the current type? I think this can be solved more easily if we can do this kind of work:

interface HTMLElement {
    addEventListener(type: string, listener: EventListener<this>, useCapture?: boolean): void;
}

var image: HTMLImageElement;
var video: HTMLVideoElement;
image.addEventListener // receives EventListener<HTMLImageElement> type
video.addEventListener // receives EventListener<HTMLVideoElement> type

@danquirk
Copy link
Member

That functionality does not exist, it's something akin to what's suggested in #285 and #229

@rayshan
Copy link

rayshan commented Jun 16, 2015

Hi all, pinging this thread. I ran into this issue with Event.target. I would imagine most of the time a target is an HTMLElement. It is a little odd that the default type assumes it isn't. I tried @saschanaz's suggestion and ran into the "duplicate identifier" issue (sorry I may be missing something, I'm pretty new to TypeScript).

Edit: this worked to quiet the warnings: (<HTMLElement>event.target).tagName

@kitsonk
Copy link
Contributor

kitsonk commented Jun 16, 2015

@rayshan the suggestion was for what should go into the lib.d.ts file and the file is auto generated based directly on the implementation of Internet Explorer. So the error you encountered is accurate. Right now the only way around it is to build without the built in lib (--noLib) and use the workaround, or do what you have done, which is cast the target. There are currently a number of challenges of dealing with the return types of the DOM right now in TypeScript (mostly because the DOM isn't the most consistent/structured/type safe/consistently implemented set of APIs).

@saschanaz
Copy link
Contributor

Now that #4910 is merged, can this be revisited?

@danquirk
Copy link
Member

danquirk commented Oct 5, 2015

@zhengbli might have some context on the status of lib.d.ts issues that require script based generation

@mhegazy
Copy link
Contributor

mhegazy commented Dec 10, 2015

PRs welcomed. here is some infromation on contributing lib.d.ts changes: https://github.com/Microsoft/TypeScript/blob/master/CONTRIBUTING.md#contributing-libdts-fixes

@mhegazy mhegazy added Help Wanted You can do this and removed Revisit An issue worth coming back to labels Dec 10, 2015
@devdanke
Copy link

devdanke commented Jan 3, 2016

I ran into this TS2339: Property 'result' does not exist on type 'EventTarget' in JS FileReader onload, and another warning for getSummary() on the event passed to FileReader's onerror.

My work-around, to suppress the horrid red squiggily lines;-) is the following:

interface FileReaderEventTarget extends EventTarget {
    result:string
}

interface FileReaderEvent extends Event {
    target: FileReaderEventTarget;
    getMessage():string;
}

Then in my app:

reader.onload = function(fre:FileReaderEvent) {
        var data = JSON.parse(fre.target.result);
        ...
    }

The generated JS codes looks good and works for me. Could this kind of solution, for unusual JS event types, be added to lib.d.ts?

I'm guessing my solution is overly simplistic. But it would help to know why.

@DaSchTour
Copy link

I would love to fix this issue. But as I see the only reference to currentTarget is inside generated webworker.generated.d.ts files in TSJS generator. I have no idea how to fix this 😞
I really hope somebody could fix this nearly 3 years old issue. Such errors may be the reason why I often hear people say that TypeScript is hard to use and that really makes me sad.

@DaSchTour
Copy link

Well. I tried to start solve this issue. I create a PR microsoft/TypeScript-DOM-lib-generator#202
Hopefully this is going into the right direction.

@ccorcos
Copy link

ccorcos commented Apr 26, 2017

I'm getting Property 'getBoundingClientRect' does not exist on type 'EventTarget'.. I think this is a good idea.

@zheeeng
Copy link

zheeeng commented Feb 11, 2018

Hope some progress on this issue. It is hard to manipulate dom with Typescript.

@DaSchTour
Copy link

This issue is four years old and the corresponding PR nearly one year I doubt this will be fixed any time soon.

@styfle
Copy link
Contributor

styfle commented Mar 1, 2018

There is a fix available in microsoft/TypeScript-DOM-lib-generator#207
But @saschanaz is blocking based on the performance.

@guntram
Copy link

guntram commented Mar 5, 2018

Casting party tonite at 11 - unload your browser tabs:
confirmationMessage(event: BeforeUnloadEvent): any {
const activeElement: HTMLElement = <HTMLElement>(<Document>event.target).activeElement;

👯‍♂️

@HolgerJeromin
Copy link
Contributor

HolgerJeromin commented Apr 3, 2018

What about adding

    readonly currentTarget: Element | null;
    readonly target: Element | null;

on UIEvent only? This is not very specific, but makes most code happy.
Perhaps even without | null as on a UIEvent both are always set

@simonh1000
Copy link

same issue here. I was trying to use Vue with Typescript and wanted to get the value of an input field as the user typed. But event.target.value would not pass the type checker even though - i think - a text inout must always produce such fields for such an event

@RyanCavanaugh RyanCavanaugh modified the milestones: Community, Backlog Mar 7, 2019
@gautamkrishnar
Copy link

gautamkrishnar commented Mar 20, 2019

We got rid of the error by adding type any to our code:

this.url = (<any>event).target.result;

@iamstiil
Copy link

What about typing Event and EventTarget?

interface Event<C = any, S = any, T = any> {
  ...
  currentTarget: EventTarget<C> | null;
  srcElement: EventTarget<S> | null;
  target: EventTarget<T> | null;
  ...
}

interface EventTarget<T = any> {
  ...
}

@adigourdi
Copy link

I encountered this issue while using the FileReader, a simple cast to the correct type fixes it

const fileReader = new FileReader();
fileReader.onload = $ev => {
  console.log($ev); // type ProgressEvent
  console.log($ev.target); // type FileReader
  // console.log($ev.target.result); // editor and autocomplete doesn't show any error
  console.log(($ev.target as FileReader).result); // casting compiles fine
};
fileReader.readAsText(file);

@alexandercerutti
Copy link

alexandercerutti commented Feb 25, 2020

Are there any updates about this topic? It would be useful to have it without force casting event.target every time or any-casting event (as @gautamkrishnar did above) . Also this is open since 2014. Thank you!

@jonmol
Copy link

jonmol commented Apr 11, 2020

Indeed, would be nice with some kind of official response to this issue before its 6th birthday

@mindplay-dk
Copy link

Yep, this is probably the Number 1 day-long nuisance when working with DOM, JSX, etc.

In fact, it's the only daily nuisance I have - and I imagine a million people have this, all day long.

It's really difficult to understand why this doesn't get any priority.

@Dean-NC
Copy link

Dean-NC commented Apr 14, 2020

Same for event.target. A very common scenario is adding a click handler to a parent element when children don't exist yet, and when there will be many children. A simple test for event.target.tagName or even classList is a common thing I do. It works....have used it for many years. I don't get intellisense for tagName/classList since EventTarget is not classified as HTMLElement, but it works.

@allejo
Copy link

allejo commented Jun 21, 2022

This is blocked by performance issue caused by generics as introducing generics doubles memory usage 😭

Going to bump this thread since the last post was in 2020. Are the performance issues with generics still there? Is there a concern about introducing performance issues to users with old versions of TS if modern TS can handle things well? Is there anything the community can do? Would a PR be welcome?

@DaSchTour
Copy link

The PRs are there, but blocked by performance issues. I would not expect this issue to be solved any time soon. I guess everybody got used to this problem.

@minecrawler
Copy link

What I can see is that there is interest in fixing this issue, and there was a PR. The only reason the PR was not merged is because its performance was bad (because of generics). Then the PR was closed, because it wasn't updated anymore.

Now, people are asking for this feature, but there is no new PR with new performance numbers. I don't feel comfortable to implement this feature since I never worked on tsc, though is there anyone else who is able to do so? From the old PR, it doesn't look like it would be a lot of work.

@nscarcella
Copy link

For anyone still interested in this feature, I created a PR here and could use some feedback regarding the performance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Help Wanted You can do this Suggestion An idea for TypeScript
Projects
None yet