Vue 3升级至3.3.x后使用withDefaults触发TypeScript错误
Vue 3.3.x升级后withDefaults结合readonly非布尔Props的TypeScript错误问题
问题场景
将Vue 3版本从3.2.x升级至3.3.x后,使用withDefaults处理带有readonly修饰符的非布尔类型Props时,出现TypeScript类型不兼容错误,而布尔类型的readonly Props则可以正常运行。
报错代码示例
<script setup lang="ts"> interface Props { readonly title: string; } // 此代码正常运行 const props = defineProps<Props>(); // 此代码报错 const props = withDefaults(defineProps<Props>(), { title: '' }); </script>
错误信息
Argument type DefineProps<Props, BooleanKey
> is not assignable to parameter type DefineProps<Readonly & {}, keyof Readonly & {}>
补充验证
- 正常运行的布尔类型示例:
withDefaults(defineProps<{readonly foo: boolean}>(), { foo: true }); - 报错的非布尔类型示例:
withDefaults(defineProps<{readonly foo: string}>(), { foo: 'foo' });
问题原因
这是Vue 3.3版本在类型推导逻辑上的小问题:当Props字段带有readonly修饰符且为非布尔类型时,defineProps返回的类型与withDefaults期望接收的参数类型出现冲突;而布尔类型因为Vue内部有特殊的类型处理逻辑,避开了这个冲突。
另外需要注意:defineProps本身会自动将所有Props设置为只读状态,不需要手动在interface中添加readonly修饰符,这也是官方推荐的写法。
解决方案
方案1:移除interface中的readonly修饰符
直接去掉Props interface里的readonly,defineProps会自动处理只读逻辑,不影响实际使用:
<script setup lang="ts"> interface Props { title: string; // 移除readonly } const props = withDefaults(defineProps<Props>(), { title: '' }); </script>
方案2:改用运行时Props定义结合类型声明
如果一定要保留interface中的readonly,可以通过显式的运行时Props定义来绕过类型推导问题:
<script setup lang="ts"> interface Props { readonly title: string; } const props = withDefaults(defineProps<Props>({ title: { type: String, required: false // 由于设置了默认值,这里设为非必填 } }), { title: '' }); </script>
内容的提问来源于stack exchange,提问作者eXception
相关产品推荐
相关产品推荐

