Skip to content

change typing of event.this to be never#3147

Merged
JoviDeCroock merged 2 commits into
masterfrom
alternative-this
May 16, 2021
Merged

change typing of event.this to be never#3147
JoviDeCroock merged 2 commits into
masterfrom
alternative-this

Conversation

@JoviDeCroock

Copy link
Copy Markdown
Member

No description provided.

@coveralls

coveralls commented May 11, 2021

Copy link
Copy Markdown

Coverage Status

Coverage remained the same at 99.622% when pulling 0b05e66 on alternative-this into 967c2c0 on master.

@JoviDeCroock JoviDeCroock merged commit 4f5891e into master May 16, 2021
@JoviDeCroock JoviDeCroock deleted the alternative-this branch May 16, 2021 10:37
MicahZoltu pushed a commit to MicahZoltu/preact that referenced this pull request Jan 21, 2023
Originally, `this` was set to `E['currentTarget']` which, based on the MDN doc linked in preactjs#2166, certainly sounds like the correct thing to do.  A couple years later it was changed to `never` in preactjs#3147 with no commentary on the PR or commit indicating why.  My guess is that this was changed so arrow functions would work, which I believe are permanently bound and cannot be rebound by the caller.

I believe that `never` is wrong because this code doesn't compile:
```ts
type TargetedEvent<Target extends EventTarget = EventTarget, TypedEvent extends Event = Event> = Omit<TypedEvent, 'currentTarget'> & { readonly currentTarget: Target }
interface EventHandler<E extends TargetedEvent> {
	(this: never, event: E): void
}
declare const apple: EventHandler<TargetedEvent<HTMLElement, Event>>
declare const event: TargetedEvent<HTMLElement, Event>
apple(event) // error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'never'.
```
Changing to `void` resolves this error and should work everywhere I believe.

I removed the comment since it no longer applies with this being `never` or `void`.  It appears that it was just forgotten when the switch from `E['currentTarget']` to `never` was made.
JoviDeCroock added a commit that referenced this pull request Feb 1, 2023
* Changes `EventHandler<...>` to have a `this` of type `void`.

Originally, `this` was set to `E['currentTarget']` which, based on the MDN doc linked in #2166, certainly sounds like the correct thing to do.  A couple years later it was changed to `never` in #3147 with no commentary on the PR or commit indicating why.  My guess is that this was changed so arrow functions would work, which I believe are permanently bound and cannot be rebound by the caller.

I believe that `never` is wrong because this code doesn't compile:
```ts
type TargetedEvent<Target extends EventTarget = EventTarget, TypedEvent extends Event = Event> = Omit<TypedEvent, 'currentTarget'> & { readonly currentTarget: Target }
interface EventHandler<E extends TargetedEvent> {
	(this: never, event: E): void
}
declare const apple: EventHandler<TargetedEvent<HTMLElement, Event>>
declare const event: TargetedEvent<HTMLElement, Event>
apple(event) // error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'never'.
```
Changing to `void` resolves this error and should work everywhere I believe.

I removed the comment since it no longer applies with this being `never` or `void`.  It appears that it was just forgotten when the switch from `E['currentTarget']` to `never` was made.

* Removes incorrectly passing test.

The type signature's intent is to make it clear to users that they cannot rely on `this` being the element in callbacks, and they should use `event.currentTarget` instead.  This test was testing that the user could unwisely ignore that.

---------

Co-authored-by: Jovi De Croock <decroockjovi@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants