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

Event types do not exist in the Window interface #19758

Closed
KevinSnyderCodes opened this issue Nov 6, 2017 · 5 comments
Closed

Event types do not exist in the Window interface #19758

KevinSnyderCodes opened this issue Nov 6, 2017 · 5 comments
Labels
Duplicate An existing issue was already created

Comments

@KevinSnyderCodes
Copy link

KevinSnyderCodes commented Nov 6, 2017

TypeScript Version: 2.7.0-dev.201xxxxx

Code

npm install typescript jsdom @types/jsdom
// example.ts

import { JSDOM } from 'jsdom';

let dom = new JSDOM(`
    <!DOCTYPE html>
    <html>
        <head>
            <title>Test DOM</title>
        </head>
        <body>
            <input type="button" id="button" />
        </body>
    </html>
`);
let window = dom.window;
let elem = window.document.getElementById('button');
elem.onclick = (ev: MouseEvent) => {
    console.log(`Button clicked, typeArg: ${ev.type}`);
}
let event: MouseEvent = new window.MouseEvent('someTypeArg');
elem.onclick(event);

Expected behavior:

TypeScript compiles, running node example.js outputs the following to console, then exits:

Button clicked, typeArg: someTypeArg

Actual behavior:

TypeScript fails to compile with the following error:

example.ts(19,36): error TS2339: Property 'MouseEvent' does not exist on type DOMWindow

@types/jsdom defines the DOMWindow interface as:

export interface DOMWindow extends Window { eval(script: string): void; }

The Window interface it extends is the one defined by TypeScript. That interface is missing definitions for the Event types, although these Event types are declared outside the Window interface. In web browsers, the Event types exist both globally and on the window object. TypeScript currently handles the former but not the latter.

jsdom does in fact implement the Event types on the dom.window object. You can modify the code above to compile and behave as expected by extending the DOMWindow interface, adding the MouseEvent type to it, and casting the dom.window object to this newly defined interface:

import { JSDOM, DOMWindow } from 'jsdom';

interface WindowWithMouseEvent extends DOMWindow {
    MouseEvent: {
        prototype: MouseEvent;
        new(typeArg: string, eventInitDict?: MouseEventInit): MouseEvent;
    }
}

let dom = new JSDOM(`
    <!DOCTYPE html>
    <html>
        <head>
            <title>Test DOM</title>
        </head>
        <body>
            <input type="button" id="button" />
        </body>
    </html>
`);
let window = dom.window as WindowWithMouseEvent;
let elem = window.document.getElementById('button');
elem.onclick = (ev: MouseEvent) => {
    console.log(`Button clicked, typeArg: ${ev.type}`);
}
let event: MouseEvent = new window.MouseEvent('someTypeArg');
elem.onclick(event);

I've spoken to the maintainer of @types/jsdom (see this issue) and they suggested raising an issue with your team instead. I agree, seeing as Event types exist on the window object in web browsers.

@aluanhaddad
Copy link
Contributor

Just FYI, a simpler workaround is to write

declare global {
  interface Window {
    MouseEvent: typeof MouseEvent;
  }
}

@DanielRosenwasser DanielRosenwasser added Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript labels Nov 7, 2017
@KevinSnyderCodes
Copy link
Author

If you'd like, I can submit a PR for this

@mhegazy
Copy link
Contributor

mhegazy commented Nov 7, 2017

To model the spec/runtime behavior correctly, window should be an alias to global. In other words all declarations that are visible in the global namespace, should be accessible through window. This applies to things like JSON, Math, HTMLElement, URLSearchParams, and MouseEvent.

We have chosen a while back to not expose these types on Window. We have added ones thought to the interface, but i am afraid there is not really a clear pattern/principal here.

See #18756 for related discussion.

I think we should revisit the original issue of making Window the global polluter and be honest to the spec. I think #14052 is a prerequisite here, but there could be other proposals too.

I have created #19816 to track general issue.

@mhegazy mhegazy added Duplicate An existing issue was already created and removed Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript labels Nov 7, 2017
@KevinSnyderCodes
Copy link
Author

Thanks for the follow-up. I'll leave this up to your team's discretion and see about adding the workaround to @types/jsdom

@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants