Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handle both React.KeyboardEvent or React.MouseEvent in one function

I'm trying to get a function to handle both click and keyboard events as I'm trying to make my web app keyboard accessible. When I use the | symbol for the type I get an error:

Property 'key' does not exist on type 'KeyboardEvent<Element> | MouseEvent<Element, MouseEvent>'.
  Property 'key' does not exist on type 'MouseEvent<Element, MouseEvent>'.

My function currently:

const handleChange = (e: React.KeyboardEvent | React.MouseEvent): void => {
  if (e.type !== 'mousedown' || e.key !== ' ') return;

  ...other stuff...
}

Can someone point me in the right direction to get this working as expected? I could just write to separate functions, but I thought that it would be nice to keep it in one.

like image 732
Mark Avatar asked Sep 03 '26 21:09

Mark


2 Answers

You can use Type Assertion to do this (https://basarat.gitbook.io/typescript/type-system/type-assertion):

const handleChange = (e: React.KeyboardEvent | React.MouseEvent): void => {
  if (e.type !== 'mousedown' || (e as React.KeyboardEvent).key !== ' ') return;

  ...other stuff...
}
like image 72
AndAC Avatar answered Sep 06 '26 09:09

AndAC


Your function doesn't know if e is a KeyboardEvent or a MouseEvent. You'll need to implement a Type Guard to let your block of code know if it is dealing with a KeyboardEvent.

import React from 'react'

/** ChangeEvent represents either a KeyboardEvent or a MouseEvent */
type ChangeEvent = React.KeyboardEvent | React.MouseEvent

/** Type-guard to check if event is a KeyboardEvent */
const isKeyboardEvent = (e: ChangeEvent): e is React.KeyboardEvent => {
    return (e as React.KeyboardEvent).getModifierState !== undefined
}

const handleChange = (e: ChangeEvent): void => {
    if (isKeyboardEvent(e)) {
        // Do keyboard stuff here
        if (e.type !== 'mousedown' || e.key !== ' ') return;
    }
}

In this case, I'm checking to see if the event has the function getModifierState defined, as that function should only be defined for KeyboardEvent and not for MouseEvent.

Playground link

like image 24
Paul Huynh Avatar answered Sep 06 '26 10:09

Paul Huynh