Vue validates a prop’s runtime type by comparing incoming values against the constructor referenced in the prop’s type field:
constructors such as String, Number, Boolean, Array, Object, Date,
Function, Symbol, Error, or a custom class. This only works if type holds an actual reference to
that constructor, for example type: String.
It is easy to write a value that merely looks like a constructor instead of being one: a quoted string (type: 'String'), a template
literal, or the result of a binary or update expression. None of these are functions, so Vue has nothing to run its
instanceof/typeof checks against.
When this happens, Vue’s prop validator does not just skip the check silently. In Vue 3, as soon as a value is passed for that prop, Vue throws
TypeError: Right-hand side of 'instanceof' is not an object while rendering the component in development, crashing it. In Vue 2, the same
failure is caught internally and downgraded to a console warning, Invalid prop type: "…" is not a constructor, so the component still
renders but the intended type is never actually checked. In production builds of either version, prop validation is stripped entirely, so neither the
crash nor the warning happens there, but the type contract is also never enforced: the code looks like it validates the prop, when in fact it never
can.
This rule also checks each element individually inside an array-shorthand type, for example type: ['String', Number], and applies to
prop declarations in both the Options API props option and the defineProps macro used in <script
setup>.
To fix this, replace the offending value with the constructor it was meant to reference.
This rule does not flag type: null. Vue’s own convention for that value is to accept a prop of any type, so it is a deliberate choice
rather than a mistaken stand-in for a constructor.
<script>
export default {
props: {
name: {
type: 'String' // Noncompliant: "String" is a string, not the String constructor
},
role: {
type: ['String', Number] // Noncompliant: "String" inside the array is not a constructor
}
}
}
</script>
<script>
export default {
props: {
name: {
type: String
},
role: {
type: [String, Number]
}
}
}
</script>
<script setup>
defineProps({
status: {
type: `String` // Noncompliant: a template literal is not the String constructor
}
})
</script>
<script setup>
defineProps({
status: {
type: String
}
})
</script>