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

Order of type declaration affecting prop value #10903

Closed
jakriese opened this issue May 10, 2024 · 3 comments
Closed

Order of type declaration affecting prop value #10903

jakriese opened this issue May 10, 2024 · 3 comments

Comments

@jakriese
Copy link

Vue version

3.4.27

Link to minimal reproduction

https://play.vuejs.org/#eNrdU01r3DAQ/StTXZzAdk0/oOA6gaQstD20pQnNoS7F2OONU1kSkux6Mf7vHWnXWpuWhZJbTrZmnkbvvZkZ2JVS665FlrDUFLpWFgzaVl1mom6U1BYG0FjBCJWWDUQEjULqFo29w1qXh+Q6DhFXM3q7QG56hYXFJXgKTvhMFFIYC43ZwoV7+Sx6j5xLuJOal8+i8wmAjbK7G6snVHROt9N4r4HY08EShucW6QSQ3r+4HAZfdxzTmE4+epSQNLJE/rzLeYsXGZvqZwziIzRoOI1O49nbbMWsIdJVvV0/GCnI6sEVzFghG1Vz1J+VrUlUxhLwGZfLSfTvjz5mdYurKV7cY/HrH/EH07tYxr5oNKg7zFjI2Vxv0e7Tm5tP2NN/SJKQlhP6RPIrGslbx3EPu25FSbRnOM/2g+91Lba3ZtNbFGYS5Yg65OjxGaNevzsh/Uj31fq1v5eJkVxcDJcb2GWDy7rzPwCuz64931x3qN0hancKZfV3Mo33lxd9O+zDfBNKrGrhuUuBwi62wg8v9h5JuLzl/jvHn3mJIm8wgSioibwrSktlgglHhiEEnn0C36+l5JiLFdC8kdkruNI63/049AKmxxOocm6mAfEynY+0QGFLDp7Od/AJ2NoHQf/r7GRocPgxzv7sULsNIEdpjNcv37DxD9ec1sk=

Steps to reproduce

  1. Create a SFC using the composition API
  2. Add a modelValue prop with the type [Boolean, String, Array] and default of false:
modelValue: {
  type: [Boolean, String, Array],
  default: false,
}
  1. Use component and provide modelValue prop an empty string ''

What is expected?

Expected is that the modelValue for the component will be set to an empty string, the value provided to the component prop

What is actually happening?

The component will mount with the modelValue prop set to true. However, by reordering the type on the prop to [String, Boolean, Array] (String first), it will correctly evaluate to an empty string (the provided value).

System Info

System:
    OS: macOS 14.4.1
    CPU: (11) arm64 Apple M3 Pro
    Memory: 100.13 MB / 18.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.12.1 - /usr/local/bin/node
    Yarn: 1.22.22 - /usr/local/bin/yarn
    npm: 10.5.0 - /usr/local/bin/npm
  Browsers:
    Chrome: 124.0.6367.156
    Safari: 17.4.1
  npmPackages:
    vue: ^3.3.0 => 3.4.27

Any additional comments?

Using a radio-like component where the modelValue will either be true/false for on/off, or it will be provided a value and will compare the value to the modelValue to check if they are identical (case of string), or if the value is included in an array of values (case of array).

@NathanFreeman
Copy link

[Boolean, String, Array]

In this case, the boolean operator has a higher precedence than the string. Therefore, it will evaluate to true.

@skirtles-code
Copy link
Contributor

This isn't happening by accident, it's intentional. There's an explicit check in the code for this specific case:

prop[BooleanFlags.shouldCastTrue] =
stringIndex < 0 || booleanIndex < stringIndex

opt[BooleanFlags.shouldCastTrue] &&
(value === '' || value === hyphenate(key))

If Boolean comes before String then it'll behave like an HTML boolean attribute. So all of these would be considered true:

<MyComp model-value />
<MyComp model-value="" />
<MyComp model-value="model-value" />

Likewise if '' or 'model-value' are passed with v-bind.

Whether this is desirable or not, it has been that way since Vue 2, so it wouldn't be an easy thing to change at this point.

@sodatea
Copy link
Member

sodatea commented May 16, 2024

It's also documented behavior: https://vuejs.org/guide/components/props.html#boolean-casting

@sodatea sodatea closed this as not planned Won't fix, can't repro, duplicate, stale May 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants