Vue Ref Used As An Operand
ID |
javascript.vue_ref_as_operand |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
JavaScript |
Tags |
reliability, suspicious-comparison, vue |
Description
Reports a Vue ref used directly as the operand of an arithmetic or a comparison operator, where the value the operator needs is ref.value.
A name counts as a ref only when its declaration is a call to one of the factories that return one. A name whose declaration cannot be resolved, or which was assigned from another variable, is left alone.
Rationale
const count = ref(0);
// Bad
const shifted = count + 1; // "[object Object]1"
const empty = count === 0; // always false
-
A ref is a wrapper object; only its
.valuemember holds the number. -
Neither operator complains about being handed an object:
+converts it to a string and concatenates, and===compares identity against a primitive and answers false, always. Both produce a plausible-looking result of the wrong kind rather than an error, so the defect reaches the screen instead of the console. -
It is easy to write because the template does not need
.value: Vue unwraps refs when it renders them, so a line moved from the template to the script loses the suffix.
Remediation
Read .value in the script. In a template, and in a reactive object, Vue unwraps the ref for you and the suffix is not needed.
// Good
const shifted = count.value + 1;
const empty = count.value === 0;
// Good — a derived value, computed once
const shifted = computed(() => count.value + 1);