Looks like you've done some homework here.
Just a quick note: I followed through to the article on https://fatih-erikli.com/pattern-matching-in-typescript.html and noticed the useEffect call doesn't define a dependency array (not even an empty one), which I believe will make the addEventListener add new listeners on every render. Having a removeEventListener on the return of the useEffect would also ensure it gets cleaned up, if pointed to the same event name / handler.
I assume it was just for illustrative purposes, but felt like I should point it out, regardless.