Marco Daniel
Marco Daniel

Reputation: 5765

React Typescript event type for both interfaces MouseEvent and TouchEvent

I am trying to write a function to handle both mouse and touch events. By combining both interfaces React.TouchEvent and React.MouseEvent, like:

onStart = (event: React.TouchEvent | React.MouseEvent) => {
    event.persist();
    console.log('event ', event);
    if (event.touches) {
        console.log(event.touches);
    }
    if (event.screenX) {
        console.log(event.screenX);
    }
};

The logs give me the expected output and I don't get any console error, it runs as it I expected. But I get errors on my editor:

Error:(94, 22) TS2339: Property 'screenX' does not exist on type 'MouseEvent | TouchEvent'. Property 'screenX' does not exist on type 'TouchEvent'.

and

Error:(90, 13) TS2339: Property 'touches' does not exist on type 'MouseEvent | TouchEvent'. Property 'touches' does not exist on type 'MouseEvent'.

How can I use both intefaces React.TouchEvent and React.MouseEvent without all this errors?

Upvotes: 13

Views: 17749

Answers (2)

Marco Daniel
Marco Daniel

Reputation: 5765

By checking for instanceof TouchEvent and instanceof MouseEvent in the condition and using the nativeEvent property inside event, it is possible to access each individual interface with no errors.

onStart = (event: React.SyntheticEvent) => {
    event.persist();
    console.log('event ', event);
    if (event.nativeEvent instanceof TouchEvent) {
        console.log(event.nativeEvent.touches);
    }

    if (event.nativeEvent instanceof MouseEvent) {
        console.log(event.nativeEvent.screenX);
    }
};

Upvotes: 19

Lin Du
Lin Du

Reputation: 102237

I will use type predicates of TypeScript. Code is more readable.

E.g.

import React, { Component } from 'react';

function isTouchEvent(e: React.TouchEvent | React.MouseEvent): e is React.TouchEvent {
  return e && 'touches' in e;
}

function isMouseEvent(e: React.TouchEvent | React.MouseEvent): e is React.MouseEvent {
  return e && 'screenX' in e;
}

export default class MyComponent extends Component {
  onStart = (event: React.TouchEvent | React.MouseEvent) => {
    event.persist();
    if (isTouchEvent(event)) {
      console.log(event.touches);
    }
    if (isMouseEvent(event)) {
      console.log(event.screenX);
    }
  };

  render() {
    return <div>my component</div>;
  }
}

Upvotes: 5

Related Questions