cat-t
cat-t

Reputation: 1376

Handle mouse vs touch events via event.type

I have a general handler function that takes in an event that can either be a mouse or touch event. Then it delegates the logic to the appropriate function. Typescript is throwing errors, though, because obviously mouseEvent !== touchEvent.

function handleStopDrag(e: MouseEvent | TouchEvent) {
    switch (e.type) {
        case 'mouseup':
            // Error: Argument of type 'MouseEvent | TouchEvent' is not assignable to parameter of type 'MouseEvent'.
            handleMouseUp(e)
            break
        case 'touchcancel':
        case 'touchend':
            // Error: Argument of type 'MouseEvent | TouchEvent' is not assignable to parameter of type 'TouchEvent'.
            handleTouchEnd(e)
            break
    }
}

function handleMouseUp(e: MouseEvent){ ... }
function handleTouchEnd(e: TouchEvent) { ... }

How do I go about declaring that the event type is a specific type based on my checks above? Or is there a better way of formatting my code to specify the event type?

Upvotes: 3

Views: 2656

Answers (2)

Akumzy
Akumzy

Reputation: 43

By using in operator to check for a property that does not exist in both Typescript was able to figure out every other thing, with less effort from my own end

function dragStart(e: MouseEvent | TouchEvent) {
  if ('touches' in e) {
    state.initialX = e.touches[0].clientX - state.xOffset
    state.initialY = e.touches[0].clientY - state.yOffset
  } else {
    state.initialX = e.clientX - state.xOffset
    state.initialY = e.clientY - state.yOffset
  }

}

Upvotes: 2

Phu Ngo
Phu Ngo

Reputation: 921

You need to use a type guard to enable TypeScript to narrow the MouseEvent | TouchEvent union type to either MouseEvent or TouchEvent type without having to resort to type assertion (<MouseEvent> e or e as MouseEvent):

  • With type predicates:
function isMouseEvent(e: MouseEvent | TouchEvent): e is MouseEvent {
    return e.type === 'mouseup'; // || e.type === 'click'...
}

then use it like

if (isMouseEvent(e)) {
    switch (e.type) {
        case 'mouseup':
            handleMouseUp(e);
            break;
} else (isTouchEvent(e)) {
    switch (e.type) {
        case 'touchcancel':
        case 'touchend':
            handleTouchEnd(e);
            break;
}
  • With instanceof:
if (e instanceof MouseEvent) {
    // switch specific MouseEvent type here or inside another delegator
    handleMouseEvent(e);
} else if (e instanceof TouchEvent) {
    handleTouchEvent(e);
}

Upvotes: 5

Related Questions