Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Template ref type inference doesn't work when using defineComponent (but does work in <script setup>) #5073

Open
catrope opened this issue Dec 19, 2024 · 3 comments

Comments

@catrope
Copy link

catrope commented Dec 19, 2024

Vue - Official extension or vue-tsc version

2.1.10

VSCode version

N/A

Vue version

3.5.13

TypeScript version

5.7.2

System Info

System:
    OS: Linux 6.8 Ubuntu 24.04.1 LTS 24.04.1 LTS (Noble Numbat)
    CPU: (12) x64 12th Gen Intel(R) Core(TM) i7-1265U
    Memory: 32.74 GB / 46.72 GB
    Container: Yes
    Shell: 5.2.21 - /bin/bash
  Binaries:
    Node: 18.20.4 - ~/.nvm/versions/node/v18.20.4/bin/node
    npm: 10.7.0 - ~/.nvm/versions/node/v18.20.4/bin/npm
    pnpm: 9.5.0 - ~/.nvm/versions/node/v18.20.4/bin/pnpm
  Browsers:
    Chrome: 131.0.6778.139
    Chromium: 128.0.6613.84

package.json dependencies

No response

Steps to reproduce

Bind a template ref to a native HTML element in a component that uses <script setup>:

<template>
    <div>
        <p>{{ msg }}</p>
        <input ref="input" v-model="msg">
        <button @click="focusInput">Focus</button>
    </div>
</template>

<script setup lang="ts">
import { useTemplateRef } from 'vue';

const input = useTemplateRef( 'input' );
function focusInput() {
    input.value?.focus();
}
</script>

Then write the same code, but using defineComponent:

<template>
    <div>
        <p>{{ msg }}</p>
        <input ref="input" v-model="msg">
        <button @click="focusInput">Focus</button>
    </div>
</template>

<script lang="ts">
import { defineComponent, useTemplateRef } from 'vue';

export default defineComponent( {
    setup() {
        const input = useTemplateRef( 'input' );
        function focusInput() {
            input.value?.focus();
        }
        return { focusInput };
    }
} );
</script>

What is expected?

In both cases, vue-tsc should automatically infer the type of the input template ref as HTMLInputElement, and so it accepts input.value?.focus() because HTMLInputElement has a focus method.

What is actually happening?

In the <script setup> case, inference works correctly. But in the defineComponent case, vue-tsc does not infer the type of the input template ref, resulting in a TypeScript error for input.value?.focus(), because the type of input.value is unknown.

Link to minimal reproduction

No response

Any additional comments?

No response

@catrope
Copy link
Author

catrope commented Dec 19, 2024

cc @zhiyuanzmj who implemented the type inference behavior for template refs

@zhiyuanzmj
Copy link
Collaborator

useTemplateRef first implemented is in vue-macros, after vue3.5 we merged in vue/language-tools.

@zhiyuanzmj zhiyuanzmj added the feature request Request new features label Dec 19, 2024
@KazariEX
Copy link
Collaborator

Just as you cannot use the define macros at there, type inference for useTemplateRef and so on is only implemented in script setup, otherwise the code will be too complex.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants