typescript - Gestionați evenimentele de mouse vs touch prin event.type


Am o funcție generală de gestionare care primește un eveniment care poate fi fie un eveniment de mouse, fie un eveniment tactil. Apoi delegă logica către funcția corespunzătoare. Totuși, Typescript aruncă erori, deoarece, evident, 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) { ... }

Cum procedez pentru a declara că tipul evenimentului este un tip specific în funcție de verificările mele de mai sus? Sau există o modalitate mai bună de a formata codul meu pentru a specifica tipul evenimentului?

Răspuns #1

Trebuie să folosești un tip de protecție (type guard) pentru a permite TypeScript să restrângă tipul uniunii MouseEvent | TouchEvent la fie MouseEvent, fie TouchEvent fără a fi nevoie să apelezi la o afirmație de tip (<MouseEvent> e sau e as MouseEvent):

  • Cu predicate de tip:
function isMouseEvent(e: MouseEvent | TouchEvent): e is MouseEvent {
    return e.type === 'mouseup'; // || e.type === 'click'...
}

apoi folosește-l ca

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

Răspunsul #2

Folosind operatorul in pentru a verifica o proprietate care nu există, Typescript a reușit să determine toate celelalte lucruri, cu mai puțin efort din partea mea

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
  }

}