Search code examples
javascripttypescriptvuejs3vue-composition-apivetur

Multiple Vue 3 watchers & Typescript ... how to use?


N.B. I'm using the @vueuse/core library to obtain some values for the below example, but I believe knowledge of the library for this question is moot.

I have the following triple watcher:

// Reactive Mouse Positionining
const { x, y } = useMouse()

//  Detect if the Mouse has been pressed:
const { pressed } = useMousePressed({ 
  target: celestiaSkyViewerRoot, 
  touch: true 
})

watch([pressed, x, y], ([newPressed, newX, newY], [prevPressed, prevX, prevY]) => {
  if (showConstellations.value) {
    if (!newPressed && newX !== prevX) {
      activeConstellation.value = getActiveConstellation(newX, newY)
    }
  }

  dragging.value = pressed.value

  if (newPressed && newX !== prevX) {
    azimuthalOffset.value -= (newX - prevX) / 6
  }
})

However, I am seeing the following Typescript errors occur:

For newX, relating to the line: activeConstellation.value = getActiveConstellation(newX, newY)

Argument of type 'number | boolean' is not assignable to parameter of type 'number'. Type 'boolean' is not assignable to type 'number'.

For newX, relating to the line: azimuthalOffset.value -= (newX - prevX) / 6

The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.

However, Vetur is only showing an issue for newY, relating to the line: azimuthalOffset.value -= (newX - prevX) / 6:

The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.

Does anyone know a possible solution for this? Essentially, these errors are stopping a reload of my dev server ... and it's very much becoming a frustrating development bottle neck ...


Solution

  • If anyone gets stuck with this like I did, this is the following solution without the need to check any types as per the above answer:

    watch([pressed, x, y] as const, ([newPressed, newX, newY], [_, prevX, prevY]) => {
       ... // do something here
    })
    

    So, you just need to cast the Vue 3 watcher multiple array: [] as const.