vuejs / core

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
https://vuejs.org/
MIT License
47.22k stars 8.26k forks source link

ref.value didn't behave as it should be in (Vue 3 Typescript) #2105

Closed luthfimasruri closed 4 years ago

luthfimasruri commented 4 years ago

Version

3.0.0-rc.10

Reproduction link

https://github.com/luthfimasruri/vue3-ts.git

Steps to reproduce

Run the app and try the calculator with another number

What is expected?

When I add 5 2, the result should be 7 NOT 52

What is actually happening?

According to vue3 docs, "Refs infer the type from the initial value", but it behaves as a string.

https://v3.vuejs.org/guide/typescript-support.html#typing-refs

stefnotch commented 4 years ago

This should explain it https://vuejs.org/v2/guide/forms.html#number

luthfimasruri commented 4 years ago

No, even with type="number" the result still the same (5+2 = 52). The code in typescript:

<script lang="ts">
import { defineComponent, onMounted, ref } from "vue";
export default defineComponent({
  setup() {
    const num1 = ref(2);
    const num2 = ref(2);
    const result = ref(0);
    function addNumbers() {
      result.value = num1.value + num2.value;
    }

    onMounted(() => {
      addNumbers();
    });

    return { num1, num2, result, addNumbers };
  }
});
</script>

But, if I don't use typescript, I could use parseInt() and it works (5+2 = 7):

<script>
import { defineComponent, onMounted, ref } from "vue";
export default defineComponent({
  setup() {
    const num1 = ref(2);
    const num2 = ref(2);
    const result = ref(0);
    function addNumbers() {
      result.value = parseInt(num1.value) + parseInt(num2.value);
    }

    onMounted(() => {
      addNumbers();
    });

    return { num1, num2, result, addNumbers };
  }
});
</script>
stefnotch commented 4 years ago

even with type="number", the value of HTML input elements always returns a string.

luthfimasruri commented 4 years ago

Yes!! Here's Reproduction link: https://github.com/luthfimasruri/vue3-ts.git

It happens in reactive as well

stefnotch commented 4 years ago

That's not a bug, that's intentional behavior, like the documentation says. You want v-model.number="num1".

According to vue3 docs, "Refs infer the type from the initial value", but it behaves as a string.

That refers to Typescript, which is purely for the IDE.

luthfimasruri commented 4 years ago

Yeah, I know that, I use <script lang="ts">

<script lang="ts">
...
</script>
luthfimasruri commented 4 years ago

Maybe it's the typescript compiler that didn't understand Vue syntax,

stefnotch commented 4 years ago

I'll repeat it one more time

While this is initially a number and Typescript correctly identifies it as such. const num1 = ref(2);

However, do not confuse it with actual strict typing like in other languages. The following still works and will assign a string to a number. num1.value = "hello world" as any"

And, as soon as you use v-model like this, num1 gets set to a string. This is what the documentation says and this is intentional. (Sadly Vetur does not catch cases like this yet.) <input v-model="num1"/>

Then, after v-model set your number to a string, adding it to something else results in a string concatenation result.value = num1.value + num2.value;

And thus you're getting the behavior that you're seeing.

luthfimasruri commented 4 years ago

Ok, that absolutely makes sense @stefnotch, Thanks!!!! 👍