core icon indicating copy to clipboard operation
core copied to clipboard

`defineProps` & `ref` types mismatch

Open lukemovement opened this issue 5 months ago • 2 comments

Vue version

3.5.16

Link to minimal reproduction

https://play.vuejs.org/#eNqlU8GO0zAQ/RXjS1upJEJwKt2VAK20cIAVi7QXX0Iybb04dmRP2qIo/87YTtKQsmWlPcWeeTPz3vil4R+qKtnXwFd87XIrK2QOsK6uhZZlZSyyhlnYsJZtrCnZjKCzIXWflZWCT4ZuGjRGiOBJ6kO+q+DvR30i/EHi7lYWBejlKGJqjMFhUpK6kJ1RC6Fzox1Rm3RgV57cXMPhrPl8saDCadlpzP8q+9rSbTvs7BaUMuzBWFW8mi2EXqdxY7QruiBQmwyBboytd2+umyYUt+06pVuISl3VyPavS1OAuhKc8oKzNCan21wdBkoEnUqnugAYFP2FGaJd+3U6oseXHB2p28ht8uiMprdvPAPBcxouFdhvFUpSL/iKhYzPZST+8CXE0Naw7OP5DvJf/4g/uqOPCX5nwYHdkxmGHGZ2CxjTN/df4UjnIUnLqRWhLyS/gzOq9hwj7GOtC6I9wgW2n4PzpN7+cDdHBO16UZ6oR7YBLzhZ1e/9Keknum+Td6FO6Ja22Nv80s/zEtMXsJEaOkbzQEdnJXjFE7MITozIkn3NnTVVV3Fy0eqcTA8YmIwxQ5BgsfklxxdyHw50dMpg7+o0xqcGjDITdLQ7OIZd5Spz7oxifIWq/qlk3n28OLD4e8UcWnpd2hUhrNxTd/oahByhmKJIg2f9xLDTUzxrXsvbP0uQ1kU=

Steps to reproduce

Use a class with a private or protected property as the Type to be passed through a components props (E.g. defineProps). An error will appear in the parent component.

What is expected?

An error should not appear when passing the correct type to the child component.

What is actually happening?

The defineProps method exposes the private and protected properties. This needs to be consistent with the behaviour of the ref method to prevent a mismatch with the types.

System Info

System:
    OS: Linux 6.8 Ubuntu 22.04.5 LTS 22.04.5 LTS (Jammy Jellyfish)
    CPU: (16) x64 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
    Memory: 4.54 GB / 15.36 GB
    Container: Yes
    Shell: 5.1.16 - /bin/bash
  Binaries:
    Node: 22.14.0 - ~/.nvm/versions/node/v22.14.0/bin/node
    Yarn: 4.7.0 - ~/Repositories/workspace/node_modules/.bin/yarn
    npm: 10.9.2 - ~/.nvm/versions/node/v22.14.0/bin/npm
  Browsers:
    Chrome: 136.0.7103.113

Any additional comments?

No response

lukemovement avatar Jul 01 '25 15:07 lukemovement

I have the same problem

Srammark avatar Jul 20 '25 02:07 Srammark

It's mainly because of the access permissions of private/protected attributes. Due to the soft privacy of TS, during compilation: TypeScript believes that external code cannot access private/protected, and the type checking of Vue Props also occurs during compilation. Therefore, there is a type mismatch. However, at runtime:

{
    publicProperty: "public",
    protectedProperty: "private" // ✅ This property actually exists!
}

It can be understood that TS tells you that private does not exist externally. But in fact, this property physically exists and can be accessed. However, during the Props type checking, it requires that this "non - existent" property must exist.

const sampleWithHidden = ref(new SampleWithHidden());
// actually
{
  value: {
    publicProperty: "public",
    protectedProperty: "private"  
  }
}

// in typescript:
const sampleWithHidden: Ref<SampleWithHidden> = ref(new SampleWithHidden());
sampleWithHidden.value.publicProperty; // ✅ 
sampleWithHidden.value.protectedProperty; // ❌private

You can use "interface" or "public" to avoid this problem.Playground

xiaocainiao633 avatar Oct 12 '25 08:10 xiaocainiao633