Description
Vue version
3.5.12
Link to minimal reproduction
Steps to reproduce
- Export a symbol in a typescript file
a.ts
// a.ts
export const MySmbol = Symbol();
- In a Vue file
Comp.vue
with<script setup lang="ts">
import and use the symbol as prop type and default: - Update the prop type to be a union of the symbol type and some other inferable type, e.g.,
boolean
. - Use the symbol as default value:
// Comp.vue
<script setup lang="ts">
import { MySmbol } from "./a";
withDefaults(defineProps<{
value?: typeof MySmbol | boolean;
}>(), { value: MySymbol });
</script>
<template>
renders
</template>
==> Check the JS output, and you can see that only the boolean
type of the type union is inferred:
props: {
value: { type: [Boolean], default: MySymbol }
},
- Switch to
Prod
mode - Create a second component, import and use the first component:
// App.vue
<script setup>
import Comp from "./Comp.vue";
</script>
<template>
<Comp />
</template>
- Switch to
DEV
mode.
==> Now you will get the error:can't convert symbol to string
Why is the DEV mode switching relevant?
We are building a component library and there we use symbols as explicit defaults for special default behaviors.
This issue was only encountered when a user tried to develop (in dev mode) using the compiled lib (in prod mode).
See also: SchwarzIT/onyx#1980 (comment)
What is expected?
- The symbol type should be inferred correctly or no runtime check at all should be happening:
props: {
value: { type: [Symbol, Boolean], default: MySymbol }
},
or
props: {
value: { default: SYMBOL }
},
- No error when a (PROD) compiled component is used for development
What is actually happening?
Vue's compiler inferred the prop type used for runtime validation as Boolean
, even though the typescript type is typeof unique symbol | boolean
. This causes the runtime validation to fail and trying to log an error. Because Vue tries to create an error message using implicit string conversions and symbols cannot be implicitly converted to a string, the JS runtime throws: Uncaught (in promise) TypeError: can't convert symbol to string
System Info
System:
OS: macOS 13.6.7
CPU: (10) arm64 Apple M1 Max
Memory: 81.38 MB / 32.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 20.17.0 - ~/Library/Caches/fnm_multishells/37685_1729492712079/bin/node
Yarn: 3.4.1 - ~/Library/Caches/fnm_multishells/37685_1729492712079/bin/yarn
npm: 10.8.2 - ~/Library/Caches/fnm_multishells/37685_1729492712079/bin/npm
pnpm: 9.7.1 - ~/Library/Caches/fnm_multishells/37685_1729492712079/bin/pnpm
bun: 1.1.21 - ~/.bun/bin/bun
Browsers:
Brave Browser: 122.1.63.169
Edge: 130.0.2849.46
Safari: 17.5
Any additional comments?
We try to use symbols as explicit defaults in place of undefined
, because the implicit default for boolean
is false
.
You can find playground examples with different usages of unique symbols here:
https://play.vuejs.org/#__PROD__eNp9Ul1LwzAU/SuXPCmMil8vc06c+KA4J24gQkBqezuraRKSdHbM/Xdv0nbWKXtqcs+5t+eenBW71DpalMj6bGATk2sHFl2pQcRyfs6Zs5wNucwLrYyDFUyfx6PJXQ+my+JViQejdHuemJFSAmPZgycTa40G1pAZVQBn0YEmJo0645LLFLNcou+1gxWXAPV0TGdLjZOsHnfR7/yD2gCUFMsthqOryhpRgVTkVTtnG4cveK0VBmb70/Gvjq1dAvMzrJMS2iw2aOYMCV4P9/bpMzio3SOv6OKw0CJ2SDcAg7SxsZ7TqbMeeZsomeXz6N0qSQ8QvOAsUYXOBZqJdrmSZFofAuKxWAj1eRtqzpTYa+vJGyYf/9TfbeVrnD0YtGgWyNkGc7GZo6vh6+k9VnTegIVKS0HsHeAjWiVKr7GmjUqZkuwOL6i9CT7ncj6z15VDadulvFDPXAc+Z5TCqx2r/8g9jk5CH5lPLoZkRc6SgViFlJKr1rWPft486R5n42V95My/WEP2EekkjfjbofpL3MRjMz20dvPVbWpTMxsSf/aLRvpfFhQO2pb0H0en0eERW38DPKE6Rw==