admin管理员组

文章数量:1296348

i want to to add options to scroll event of an element in TypeScript like this:

element.addEventListener("scroll", () => { }, { capture: true, passive: true });

But TypeScript throw an syntax error: Argument of type '{ capture: true, passive: true }' is not assignable to parameter of type 'boolean'.
I know the reason of error is TypeScript does not define an options argument for addEventListener. It just only have useCapture argument. We can see it in lib.dom.d.ts:

addEventListener<K extends keyof ElementEventMap>(type: K, listener: (this: Element, ev: ElementEventMap[K]) => any, useCapture?: boolean): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;

I found an open issue and a walk around in github but it seems plicate and i am not sure it is right.
By the way, i also want to know why TypeScript did not define options argument for addEventListener?

Any help would be appreciated. Thanks!

i want to to add options to scroll event of an element in TypeScript like this:

element.addEventListener("scroll", () => { }, { capture: true, passive: true });

But TypeScript throw an syntax error: Argument of type '{ capture: true, passive: true }' is not assignable to parameter of type 'boolean'.
I know the reason of error is TypeScript does not define an options argument for addEventListener. It just only have useCapture argument. We can see it in lib.dom.d.ts:

addEventListener<K extends keyof ElementEventMap>(type: K, listener: (this: Element, ev: ElementEventMap[K]) => any, useCapture?: boolean): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;

I found an open issue and a walk around in github but it seems plicate and i am not sure it is right.
By the way, i also want to know why TypeScript did not define options argument for addEventListener?

Any help would be appreciated. Thanks!

Share Improve this question edited Oct 25, 2017 at 7:05 Duannx asked Oct 25, 2017 at 6:11 DuannxDuannx 8,7461 gold badge31 silver badges65 bronze badges 7
  • A quick (but maybe ugly) fix would be to just cast element to any while calling addEventListener. (<any>element).addEventListener("scroll", () => { }, { capture: true, passive: true });. Not 100% sure, but I think that will work – Fredrik Lundin Grande Commented Oct 25, 2017 at 6:15
  • @FredrikLundin: It will remove typescript error but does it actual add options to the event? How can i test to ensure it? – Duannx Commented Oct 25, 2017 at 6:22
  • Typescript is just a helping out at pile time. Using the any type is there for wildcard situations, where you want to opt out of types. The underlaying element object is just the same, typed or not typed – Fredrik Lundin Grande Commented Oct 25, 2017 at 6:26
  • did you check 'Safely detecting option support' section on link: developer.mozilla/en-US/docs/Web/API/EventTarget/…? – tlt Commented Oct 25, 2017 at 6:29
  • @FredrikLundin: You might right. Can you post an answer please? – Duannx Commented Oct 25, 2017 at 6:53
 |  Show 2 more ments

4 Answers 4

Reset to default 4

As a workaround for situations like this, you can always cast your object to the any type.

(<any>element).addEventListener("scroll", () => { }, { capture: true, passive: true });

The any type is used to opt-out of typescripts typing system. Meaning you will work on an unknown type that you can treat any way you like, without the typescript piler plaining.

You can read more on the any type here!

Since interfaces in Typescript are open-ended you can add functions do the Document interface by re-declaring it in your application:

 interface Document {
    addEventListener(event: "scroll", listener: (event: Event) => void, options?: {
        passive?: boolean;
        once?: boolean;
        capture?: boolean;
      }      
  );
}

The you will be able to use the overload you defined, or any overload (or any other method) defined dor Document in lib.d.ts:

document.addEventListener("scroll", ()=> {}, {
    capture: true,
    once: true
});

document.addEventListener("scroll", ()=> {}, true);

I can't speak to why this was not included, there might be some corner cases where it will interfere method resolution for other overloads of addEventListener. (Note: I did not test this extensively so you may run into this issue).

I think the approach from linked github is fine. If you want, you could do inline variation. but it boils down to the same:

(element.addEventListener as (
      type: string,
      listener: (event: Event) => void,
      options?: { useCapture?: boolean, passive?:boolean }
    ) => void)("scroll", () => { }, {/*here use userCapture & passive*/})

so what you are effectively doing here is casting element.addEventListener method into arrow function and extending its signature so that typescript piler can accept it.

You can just use as unknown as EventListenerOptions to get this to work as well, e.g.

element.addEventListener("scroll", () => { }, ({ capture: true, passive: true } as unknown) as EventListenerOptions);

本文标签: javascriptHow to add passive option to addEventListener in TypeScriptStack Overflow