--- title: Boolean Props Default to false, Not undefined impact: MEDIUM impactDescription: TypeScript expects optional boolean to be undefined but Vue defaults it to false, causing type confusion type: gotcha tags: [vue3, typescript, props, boolean, defineProps] --- # Boolean Props Default to false, Not undefined **Impact: MEDIUM** - When using type-based `defineProps`, optional boolean props (marked with `?`) behave differently than TypeScript expects. Vue treats boolean props specially: an absent boolean prop defaults to `false`, not `undefined`. This can cause confusion when TypeScript thinks the type is `boolean | undefined`. ## Task Checklist - [ ] Understand that Vue's boolean casting makes absent booleans `false` - [ ] Use `withDefaults()` to be explicit about boolean defaults - [ ] Consider using non-boolean types if `undefined` is a meaningful state - [ ] Document this Vue-specific behavior for your team ## The Gotcha ```vue ``` ## Why This Happens Vue has special "boolean casting" behavior inherited from HTML boolean attributes: ```vue ``` This is by design to match how HTML works: ```html ``` ## Solutions ### Solution 1: Be Explicit with withDefaults Make your intention clear: ```vue ``` ### Solution 2: Use a Three-State Type If you actually need to distinguish "not set" from "explicitly false": ```vue ``` ### Solution 3: Use null for "Not Set" ```vue ``` ## Boolean Casting Order Vue also has special behavior when Boolean and String are both valid: ```typescript // Order matters in runtime declaration! defineProps({ // Boolean first: empty string becomes true disabled: [Boolean, String] }) // → disabled = true // → disabled = true ``` ```typescript defineProps({ // String first: empty string stays as string disabled: [String, Boolean] }) // → disabled = '' // → disabled = '' ``` With type-based declaration, Boolean always takes priority for absent props. ## Common Bug Pattern ```vue ``` **Fix:** ```vue ``` ## TypeScript Type Accuracy The Vue type system handles this, but it can be confusing: ```typescript interface Props { disabled?: boolean } const props = defineProps() // At compile time: boolean | undefined // At runtime: boolean (never undefined due to Vue's boolean casting) // TypeScript is technically "wrong" here, but the withDefaults usage // or explicit false default can help align expectations ``` ## Reference - [Vue.js Props - Boolean Casting](https://vuejs.org/guide/components/props.html#boolean-casting) - [GitHub Issue: Boolean props default to false](https://github.com/vuejs/core/issues/8576) - [TypeScript Vue 3 Props](https://madewithlove.com/blog/typescript-vue-3-and-strongly-typed-props/)