vuejs / language-tools

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

emit type errors with vue@3.5 #4628

Closed gu-stav closed 1 month ago

gu-stav commented 2 months ago

Vue - Official extension or vue-tsc version

2.0.29

VSCode version

Version: 1.91.1 Commit: f1e16e1e6214d7c44d078b1f0607b2388f29d729 Date: 2024-07-09T22:07:46.768Z (3 wks ago)

Vue version

@vue/canary@3.20240715.0-minor.0

TypeScript version

5.5.3

System Info

System:
    OS: macOS 14.5
    CPU: (12) arm64 Apple M3 Pro
    Memory: 49.23 MB / 18.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.11.0 - ~/.nvm/versions/node/v20.11.0/bin/node
    npm: 10.2.4 - ~/.nvm/versions/node/v20.11.0/bin/npm
    pnpm: 8.14.1 - ~/Library/pnpm/pnpm
  Browsers:
    Chrome: 126.0.6478.185
    Edge: 127.0.2651.74
    Firefox Nightly: 130.0a1
    Safari: 17.5

Steps to reproduce

  1. Create a new component
<script setup lang="ts">
function onSubmit(event: Event) {}
</script>

<template>
    <form @submit="onSubmit" />
</template>
  1. Run vue-tsc --build --force

What is expected?

Running vue-tsc --build --force should not error on this.

What is actually happening?

The following type error is thrown

src/Repo.vue:6:6 - error TS2345: Argument of type '{ onSubmit: (event: Event) => void; }' is not assignable to parameter of type 'ClassAttributes<HTMLFormElement> & FormHTMLAttributes<HTMLFormElement> & Record<string, unknown>'.
  Type '{ onSubmit: (event: Event) => void; }' is not assignable to type 'FormHTMLAttributes<HTMLFormElement>'.
    Types of property 'onSubmit' are incompatible.
      Type '(event: Event) => void' is not assignable to type 'FormEventHandler<HTMLFormElement>'.
        Types of parameters 'event' and 'event' are incompatible.
          Type 'FormEvent<HTMLFormElement>' is not assignable to type 'Event'.

6     <form @submit="onSubmit" />

Vscode does not display the error inline, which is the reason I suspected vue-tsc instead of vue.

Screenshot 2024-07-31 at 08 39 25

Link to minimal reproduction

No response

Any additional comments?

I having the same problem in different shapes throughout the codebase:

src/components/Link/Link.vue:28:8 - error TS2345: Argument of type '{ href: string; "aria-current": false | "page"; onClick: (e?: MouseEvent) => Promise<void | NavigationFailure>; }' is not assignable to parameter of type 'ClassAttributes<HTMLAnchorElement> & AnchorHTMLAttributes<HTMLAnchorElement> & Record<string, unknown>'.
  Type '{ href: string; "aria-current": false | "page"; onClick: (e?: MouseEvent) => Promise<void | NavigationFailure>; }' is not assignable to type 'AnchorHTMLAttributes<HTMLAnchorElement>'.
    Types of property 'onClick' are incompatible.
      Type '(e?: MouseEvent | undefined) => Promise<void | NavigationFailure>' is not assignable to type 'MouseEventHandler<HTMLAnchorElement>'.
        Types of parameters 'e' and 'event' are incompatible.
          Type 'MouseEvent<HTMLAnchorElement, MouseEvent>' is missing the following properties from type 'MouseEvent': layerX, layerY, offsetX, offsetY, and 16 more.

28       <a
src/components/Input/Input.vue:164:9 - error TS2769: No overload matches this call.
  Overload 1 of 3, '(e: "change", event: Event): void', gave the following error.
    Argument of type 'ChangeEvent<HTMLInputElement>' is not assignable to parameter of type 'Event'.
  Overload 2 of 3, '(e: "blur", event: Event): void', gave the following error.
    Argument of type '"change"' is not assignable to parameter of type '"blur"'.
  Overload 3 of 3, '(e: "keyup", event: Event): void', gave the following error.
    Argument of type '"change"' is not assignable to parameter of type '"keyup"'.

164         emit('change', event)
src/components/InlineNavigation/Item.vue:58:8 - error TS2345: Argument of type '{ href: string; "aria-current": boolean; onClick: (event: Event) => Promise<void>; }' is not assignable to parameter of type 'ClassAttributes<HTMLAnchorElement> & AnchorHTMLAttributes<HTMLAnchorElement> & Record<string, unknown>'.
  Type '{ href: string; "aria-current": boolean; onClick: (event: Event) => Promise<void>; }' is not assignable to type 'AnchorHTMLAttributes<HTMLAnchorElement>'.
    Types of property 'onClick' are incompatible.
      Type '(event: Event) => Promise<void>' is not assignable to type 'MouseEventHandler<HTMLAnchorElement>'.
        Types of parameters 'event' and 'event' are incompatible.
          Type 'MouseEvent<HTMLAnchorElement, MouseEvent>' is missing the following properties from type 'Event': cancelBubble, composed, returnValue, srcElement, and 7 more.

58       <a :href="`#${props.target}`" :aria-current="isActive" @click.prevent="handleNavigation">
          ~

Another interesting instance of this seems to be the following:

<input
    v-else
    :type="type"
    v-bind="$attrs"
    @change="
      (event) => {
        emit('change', event)
      }
    "
    @blur="
      (event) => {
        emit('blur', event)
      }
    "
    @keyup="
      (event) => {
        emit('keyup', event)
      }
    "
  />

In Vscode the type is inferred properly:

Screenshot 2024-07-31 at 08 58 50

but vue-tsc throws an error

src/components/Input/Input.vue:173:8 - error TS7006: Parameter 'event' implicitly has an 'any' type.

173       (event) => {

I have installed the vue canary minor version as documented here: https://vuejs.org/about/releases. My package.json now looks like:

{
  "dependencies": {
    "vue": "npm:@vue/canary@3.20240715.0-minor.0"
  },
  "overrides": {
    "vue": "npm:@vue/canary@3.20240715.0-minor.0",
    "@vue/compiler-core": "npm:@vue/compiler-core-canary@3.20240715.0-minor.0",
    "@vue/compiler-dom": "npm:@vue/compiler-dom-canary@3.20240715.0-minor.0",
    "@vue/compiler-sfc": "npm:@vue/compiler-sfc-canary@3.20240715.0-minor.0",
    "@vue/compiler-ssr": "npm:@vue/compiler-ssr-canary@3.20240715.0-minor.0",
    "@vue/reactivity": "npm:@vue/reactivity-canary@3.20240715.0-minor.0",
    "@vue/runtime-core": "npm:@vue/runtime-core-canary@3.20240715.0-minor.0",
    "@vue/runtime-dom": "npm:@vue/runtime-dom-canary@3.20240715.0-minor.0",
    "@vue/server-renderer": "npm:@vue/server-renderer-canary@3.20240715.0-minor.0",
    "@vue/shared": "npm:@vue/shared-canary@3.20240715.0-minor.0",
    "@vue/compat": "npm:@vue/compat-canary@3.20240715.0-minor.0"
  }
}

I hope that helps. If you need any more help reproducing the issue please let me know 🙏🏼

gu-stav commented 2 months ago

Maybe another interesting bit to this: I am observing other obscure errors whenever conditional types are in play. For example:

<script setup lang="ts">
type EditCatalogTranslationFormCommonProps = {}

type EditCatalogTranslationFormConditionalProps =
  | {
      /* Catalog translation initial data */

      translationInitial?: GetCatalogTranslation.Response['data']
    }
  | {
      /* Catalog translation source */

      translationSource?: GetCatalogTranslation.Response['data']
    }

type EditCatalogTranslationFormProps = EditCatalogTranslationFormCommonProps &
  EditCatalogTranslationFormConditionalProps

const props = defineProps<EditCatalogTranslationFormProps>()

const translationInitialSectionsFlat = computed(() =>
  flattenSections('translationInitial' in props ? (props.translationInitial?.sections ?? []) : [])
)

</script>

<template>

  <span>
    {{
      (
        translationInitialSectionsFlat.find(
          (section) => section.type === row.type && section.id === props.row.id
        ) as RowMeasure | undefined
      )?.description?.text ?? t('Missing translation')
    }}
  </span>

</template>

While translationInitialSectionsFlat is properly typed in script setup it suddenly looses its type in the template:

Script

Template

As soon as I remove & EditCatalogTranslationFormConditionalProps the type is inferred properly.

davidmatter commented 1 month ago

Hi @gu-stav you seem to be using vue @ version 3.2 - is that correct? Please try using just vue@latest (5.4.x). There seems to be something wrong with your canary override

gu-stav commented 1 month ago

Hi @davidmatter. I am using the latest canary version of vue@3.5.

Screenshot 2024-08-05 at 08 24 59
davidmatter commented 1 month ago

This canary release is outdated. Please use 3.4.x or the 3.5 alpha version.

gu-stav commented 1 month ago

@davidmatter How is this canary release outdated? This is what the offical documentation about using the canary version is recommending: https://vuejs.org/about/releases using npx install-vue@canary-minor

Also: the canary release is from Junly the 15th and since then there hasn't been a new canary release.

davidmatter commented 1 month ago

Not sure about that, you might want to ask in @vue/core - there might be an issue with canary releases

davidmatter commented 1 month ago

I've created a PR @ vue/core https://github.com/vuejs/core/pull/11516 This will fix the broken canary release workflow.

gu-stav commented 1 month ago

Thanks a lot @davidmatter 🙏🏼