-
-
Notifications
You must be signed in to change notification settings - Fork 8.8k
Description
What problem does this feature solve?
Vue has an unexpected behavior where if you do this:
props: {
foo: {
type: Boolean,
required: false
}
}
...the value of foo
, if not specified, will be false
instead of undefined
. This is somewhat unexpected, as noted in vuejs/vue#7646 and vuejs/vue#4792, but my guess is that this was a conscious choice by Vue to imitate the behavior certain HTML values, at least their values in the DOM.
The problem comes in the TypeScript extension of Vue. Say you have this:
<script setup lang="ts">
interface Props {
foo?: boolean
}
defineProps<Props>()
</script>
TypeScript is very clear about interface syntax, which is that foo?: boolean
means that the value of foo
will be undefined
if it is not specified. The type, in fact, is not boolean
but boolean | undefined
from TypeScript's perspective.
Meaning, the most accurate translation of TypeScript to Vue's JavaScript API when passing an interface would be:
props: {
foo: {
type: Boolean,
required: false,
default: undefined
}
}
I would consider this a bug of not interpreting a TypeScript interface accurately, BUT it could be also considered a feature request as supporting optional properties in TypeScript, which may have not been fully implemented.
What does the proposed API look like?
Ideally, the API would be identical:
<script setup lang="ts">
interface Props {
foo?: boolean
}
defineProps<Props>()
</script>
However, it's rational that there would be concern about breaking changes, so this is what I propose, which is a compile-time error vs a possible runtime change:
- If a TypeScript type is passed into
withDefaults(defaultProps<Props>, {})
, anyboolean
type should be required in thewithDefaults
object, so that the developer can make it clear if they are intending the default Vue behavior, or the default TypeScript behavior. - Ideally, a
withDefaults
macro would be required with adefaultProps
macro if, again, there are boolean types in the interface, but that could be considered too high of a burden for developers.
So, my proposal, at minimum, is that the provided script block throws an error (or I can set a TypeScript strictness check to throw an error?). Thanks for considering this.