'Vue 3 how to pass an optional boolean prop?

I'm building an app with Vue 3 and TS 4.4 and bundled with Vite 2. I've got a LoginPage.vue file with these contents:

<script lang="ts" setup>
const props = defineProps<{
  message?: string;
  redirectOnSubmit?: boolean;
  showRegisterLink?: boolean;
}>();

console.log({ ...props });
</script>

<template>
  ... login form and whatnot
</template>

This component is being passed to vue-router

export const router = createRouter({
  history: createWebHistory(),
  routes: [
    { name: RouteName.LOGIN, path: "/login", component: LoginPage },
    { name: RouteName.REGISTER, path: "/register", component: RegisterPage },
  ],
});

The problem I'm having is when the login page setup script gets run, it logs this:

{ redirectOnSubmit: false, showRegisterLink: false, message: undefined }

Why are my optional boolean props being forced to false instead of undefined? Is there any way to turn this off? If I switch message to message?: boolean, it also gets switched to false.

I'd like to default these props to true if nothing is passed, but as-is there's no way for me to distinguish between passing false and omitting the props entirely.



Solution 1:[1]

Vue defaults Boolean props to false if no default was specified in the prop declaration. The author of Vue explains the reasoning:

The boolean casting follows the same rule of a boolean attribute: presence of any value are casted to true, absence means false.

To default the props to true, declare the prop with a default option of true, using the object-based syntax for the prop declaration, as seen in this Options API example:

<script>
export default {
  props: {
    myOptionalBool: {
      type: Boolean,
      default: true, ?
    }
  }
}
</script>

Option 1: defineProps(props)

In <script setup>, defineProps() accepts the prop declaration object (shown above) as a function argument. Since defineProps() only accepts either the function argument or the generic type argument, all props would have to be declared in the function argument:

<script lang="ts" setup>
const props = defineProps({
  message: String,
  showRegisterLink: {
    type: Boolean,
    default: true,
  },
  redirectOnSubmit: {
    type: Boolean,
    default: true,
  },
})
</script>

demo 1

Option 2: withDefaults() and defineProps<T>()

The withDefaults() macro can be used with defineProps<T>() to specify default values for specific props:

<script lang="ts" setup>
interface Props {
  message?: string
  redirectOnSubmit?: boolean
  showRegisterLink?: boolean
}
const props = withDefaults(defineProps<Props>(), {
  redirectOnSubmit: true,
  showRegisterLink: true,
})
</script>

demo 2

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1