Skip to content

Using expose in options API breaks vue-tsc typing in templates in Vue 3.5 #5069

@catrope

Description

@catrope

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: 34.84 GB / 46.72 GB
    Container: Yes
    Shell: 5.2.21 - /bin/bash
  Binaries:
    Node: 20.16.0 - ~/.nvm/versions/node/v20.16.0/bin/node
    npm: 10.8.1 - ~/.nvm/versions/node/v20.16.0/bin/npm
  Browsers:
    Chrome: 131.0.6778.139
    Chromium: 128.0.6613.84

package.json dependencies

No response

Steps to reproduce

Write a component using the Option API, and use expose to expose some properties but not others. For example:

<template>
    <p>{{ msg }}</p>
    <input v-model="msg">
    <p>{{ msg2 }}</p>
    <input v-model="msg2">
</template>

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

export default defineComponent( {
    expose: [ 'msg' ],
    setup() {
        const msg = ref( 'hello' );
        const msg2 = ref( 'world' );
        return { msg, msg2 };
    }
} );
</script>

What is expected?

This should pass, which it did in Vue 3.4.x

What is actually happening?

In Vue 3.5.x, this causes the following TypeScript error (both in VSCode and when running vue-tsc on the command line):

Property 'msg2' does not exist on type 'CreateComponentPublicInstanceWithMixins<Readonly<{}>, { msg: Ref<string, string>; msg2: Ref<string, string>; }, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, ... 17 more ..., {}>'.

The same thing happens for everything (refs returned by setup, but also props and methods) that is not listed in the expose array. If you remove the expose array altogether, the error goes away.

Link to minimal reproduction

No response

Any additional comments?

It appears that Vue 3.5.x changed something that led vue-tsc to type-check the template using the public-facing version of the component instance (which only contains exposed properties) when it should be using the internal-facing version of the component instance (which contains all properties returned from setup, as well as props etc).

I tried different versions of Vue, and it appears this issue was introduced between Vue 3.4.38 and 3.5.0-alpha.1, which makes me suspect vuejs/core@75c8cf6 might have caused this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    good reproduction ✨This issue provides a good reproduction, we will be able to investigate it first🔨 p3-minor-bug

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions