vuejs / language-tools

⚡ High-performance Vue language tooling based-on Volar.js
https://marketplace.visualstudio.com/items?itemName=Vue.volar
MIT License
5.87k stars 403 forks source link

Tooling incorrectly thinks v-for will unwrap refs on enumerated items #4957

Closed DaRosenberg closed 3 weeks ago

DaRosenberg commented 3 weeks ago

Vue - Official extension or vue-tsc version

2.1.8

VSCode version

1.94.2

Vue version

3.5.12

TypeScript version

5.6.3

System Info

System:
    OS: macOS 15.1
    CPU: (12) arm64 Apple M2 Max
    Memory: 347.84 MB / 64.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.6.0 - ~/.nvm/versions/node/v22.6.0/bin/node
    npm: 10.8.2 - ~/.nvm/versions/node/v22.6.0/bin/npm
  Browsers:
    Safari: 18.1

package.json dependencies

"dependencies": {
    "@azure/service-bus": "~7.9.5",
    "@floating-ui/vue": "~1.1.5",
    "@fortawesome/fontawesome-svg-core": "~6.6.0",
    "@fortawesome/free-brands-svg-icons": "~6.6.0",
    "@fortawesome/pro-duotone-svg-icons": "~6.6.0",
    "@fortawesome/pro-regular-svg-icons": "~6.6.0",
    "@fortawesome/pro-solid-svg-icons": "~6.6.0",
    "@fortawesome/vue-fontawesome": "~3.0.8",
    "@headlessui/tailwindcss": "~0.2.1",
    "@headlessui/vue": "~1.7.23",
    "@microsoft/applicationinsights-web": "^3.3.3",
    "@microsoft/signalr": "~8.0.7",
    "@tailwindcss/container-queries": "~0.1.1",
    "@vee-validate/yup": "~4.14.6",
    "@vueuse/core": "~11.1.0",
    "@vueuse/integrations": "~11.1.0",
    "buffer": "~6.0.3",
    "collapse-white-space": "~2.1.0",
    "filesize": "~10.1.4",
    "focus-trap": "~7.5.4",
    "gravatar-gen": "~1.0.1",
    "luxon": "~3.4.4",
    "mark.js": "~8.11.1",
    "moderndash": "~3.12.0",
    "nanoid": "^5.0.7",
    "pinia": "~2.2.0",
    "pinia-orm": "~1.9.2",
    "primevue": "~3.52.0",
    "process": "~0.11.10",
    "slug": "~9.1.0",
    "string-template": "~1.0.0",
    "vee-validate": "~4.14.6",
    "vue": "~3.5.12",
    "vue-router": "~4.4.5"
},
"devDependencies": {
    "@rushstack/eslint-patch": "~1.10.4",
    "@tailwindcss/forms": "~0.5.9",
    "@tsconfig/node20": "~20.1.4",
    "@types/luxon": "~3.4.2",
    "@types/mark.js": "~8.11.12",
    "@types/node": "~20.12.13",
    "@types/slug": "~5.0.8",
    "@types/string-template": "~1.0.6",
    "@vitejs/plugin-vue": "~5.1.4",
    "@vue/eslint-config-typescript": "~13.0.0",
    "@vue/tsconfig": "~0.5.1",
    "autoprefixer": "~10.4.19",
    "eslint": "~8.57.0",
    "eslint-plugin-vue": "~9.27.0",
    "npm-run-all2": "~6.2.2",
    "postcss": "~8.4.47",
    "postcss-import": "~16.1.0",
    "tailwindcss": "~3.4.14",
    "typescript": "~5.6.3",
    "vite": "~5.4.10",
    "vite-plugin-node-polyfills": "~0.22.0",
    "vue-tsc": "~2.1.8"
}

Steps to reproduce

Consider the following component:

<script setup lang="ts">
import { computed, ref } from "vue";

const items = computed(() =>
{
    return [
        { name: "Daniel", isBold: ref(false) },
        { name: "Chris", isBold: ref(false) },
    ];
});
</script>

<template>
    <ul>
        <li v-for="(item, index) in items" :key="index" :class="{'font-bold': item.isBold.value}">
            {{ item.name }}
        </li> 
    </ul>
</template>

This code works fine at runtime using npm run dev.

But while editing this file in VSCode the following error is shown:

Screenshot 2024-10-28 at 18 47 14

The same error is also emitted when doing npm run build:

src/views/Repro.vue:15:85 - error TS2551: Property 'value' does not exist on type 'boolean'. Did you mean 'valueOf'?

15   <li v-for="(item, index) in items" :key="index" :class="{'font-bold': item.isBold.value}">
                                                                                       ~~~~~

  node_modules/typescript/lib/lib.es5.d.ts:548:5
    548     valueOf(): boolean;
            ~~~~~~~~~~~~~~~~~~~
    'valueOf' is declared here.

Removing the .value accessor makes the compiler and IDE happy, but fails at runtime because this property is actually a ref (not unwrapped). It seems the editor and transpiler think this property would be unwrapped by the v-for directive, but this is definitely not happening at runtime.

What is expected?

I expect one of two things:

  1. Either the isBold ref is indeed unwrapped by the v-for directive, and using .value is not needed
  2. Or the isBold ref is not unwrapped, and the editor and transpiler recognize that it's a ref

What is actually happening?

See repro steps above.

Transpiler and IDE both think the .isBold property is a boolean but at runtime it is a Ref<boolean>.

Link to minimal reproduction

No response

Any additional comments?

I'm using the latest versions of both Vue, TypeScript and the VSCode extension.

obulat commented 3 weeks ago

I get the same error in the CI when I update vue-tsc. toggle.state is a computed, but vue-tsc reports it as a boolean (the type of its .value)

https://github.com/WordPress/openverse/blob/f9b176940575ed5f9d09403a72f57c8394a7ad61/frontend/src/components/VSafeBrowsing/VSafeBrowsing.vue#L84-L93

KazariEX commented 3 weeks ago

Duplicate of #4948