Search code examples
reactjstypescriptcompiler-errorsrxjs

How to set target in typescript to fromEvent() in rxjs


I'm using 'rxjs' library alongside typescript. Issue is, I can't figure out how to pass a simple button to fromEvent() from rxjs

Trying this makes the compiler complain:

import React from 'react';
import * as rx from 'rxjs';

const RXComponent: React.FC = () => {

    rx.fromEvent(document.getElementById('dblbutton'), 'click')

    return (
        <form>
            <input type='button' id='dblbutton' value='Click me!'>
            </input>
        </form>
    )
}

export default RXComponent;

This throws the following exception:

Argument of type 'HTMLElement | null' is not assignable to parameter of type 'FromEventTarget'. Type 'null' is not assignable to type 'FromEventTarget'. TS2345

enter image description here

I tried to change the definition to a node-list as per documentation:

List of DOM Nodes, returned for example by document.querySelectorAll or Node.childNodes.

Although this collection is not event target in itself, fromEvent will iterate over all Nodes it contains and install event handler function in every of them. When returned Observable is unsubscribed, function will be removed from all Nodes.

const btn = document.querySelectorAll('#dblbutton')
const obs = rx.fromEvent(btn, 'click')
obs.subscribe(x => console.log(x))

Which technically works and stops the compiler from complaining, but if I open the actual website on localhost I just get bunch of errors referencing the library.

enter image description here

Any idea what am I doing wrong?


Solution

  • I encountered the same problem, you just need to coerce (or cast) type explicitly, so I made a little helper for this

    import * as Rx from 'rxjs'
    import { FromEventTarget } from 'rxjs/internal/observable/fromEvent'
    
    const
        mkEventTarget = (qs: string): FromEventTarget<Event> =>
            document.querySelector (qs) as FromEventTarget<Event>
    
      , evClicks: Rx.Observable<Event> = Rx.fromEvent (mkEventTarget ("#btn"), "click")
    
    evClicks.subscribe (() => console.log ("Test"))