Mark
Mark

Reputation: 1679

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.

Upvotes: 6

Views: 5997

Answers (2)

AndAC
AndAC

Reputation: 246

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...
}

Upvotes: 9

Paul Huynh
Paul Huynh

Reputation: 3140

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

Upvotes: 3

Related Questions