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

Breaks with @types/node@18.8.5, Type '...' is not assignable to type 'Event'. ts2322 #6899

Jack-Works opened this issue Oct 17, 2022 · 3 comments · Fixed by #6855


Copy link

Vue version

(Not related)

Link to minimal reproduction

Steps to reproduce

Make sure to have vue and @types/node installed.

const T = <div onClick={() => {}} />

What is expected?

No type error

What is actually happening?

Type '() => void' is not assignable to type 'MouseEvent'. (2322)

System Info


Any additional comments?

This is caused by DefinitelyTyped/DefinitelyTyped#59905.

Vue uses the following code to get generate the signature of event handlers:

type EventHandlers<E> = {
[K in keyof E]?: E[K] extends Function ? E[K] : (payload: E[K]) => void

And Vue maintains an event map. It tests each property is assignable to Function (interface).

On the other side, @types/node introduces a new change to include browser types that are implemented in Node, which is, unfortunately, incompatible with DOM.

The PR is intended to not re-declaring the existing type (from libdom) if possible (which is not possible in TypeScript), but they're doing it in the wrong way.

It augmented the global Event interface with __Event

declare global {
    interface Event extends __Event {}
    // ...

And __Event is defined in the following way:

type __Event = typeof globalThis extends { onmessage: any, Event: infer T }
//                                                                ~~~~~~~ wrong
? T
: // Node's definition ...

It tries to reuse the global Event value (which is NOT the global interface Event), which means __Event is the constructor of DOM Events.

Because (AFAIK) it is impossible to "reflect" a type out to solve this problem.

// Note: globalThis is a namespace
namespace Test {
  export interface Name { value: 1 }
  export var Name: Function & { value: 2 }

type _ = [
  Test.Name['value'], // 1
  typeof Test.Name['value'], // 2

  typeof Test extends { Name: infer N } ? N : never
  // Function & { value: 2 }

This brings us back to the Vue side.

With the augmented global Event interface, now all DOM events (MouseEvent, KeyboardEvent, etc) are now inherited from the global Event constructor (from the value namespace).

type EventHandlers<E> = {
  [K in keyof E]?: E[K] extends Function ? E[K] : (payload: E[K]) => void

And E[K] (Events) now all passes the extends Function test and makes all DOM JSX types broken (they're now typed as onClick?: MouseEvent | undefined).

Copy link

Also opened an issue in DT repo DefinitelyTyped/DefinitelyTyped#62759

@Jack-Works Jack-Works changed the title TypeScript incompatibility with @types/node@18.8.5 Breaks with @types/node@18.8.5, Type '...' is not assignable to type 'Event'. ts2322 Oct 17, 2022
Copy link

sxzz commented Oct 17, 2022

Related PR #6855

Copy link

LinusBorg commented Oct 21, 2022

Comment by sodatea in the PR: 15 hours ago

FYI the issue has been fixed in @types/node v18.11.1+ so you don't have to wait for this PR to be merged to update your @types/node version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet

Successfully merging a pull request may close this issue.

4 participants