Vue组件传入函数作为Props时TypeScript编译异常
Vue组件Props允许函数返回值的类型检查逻辑及禁用方案
为什么会出现这种情况
这是Vue为适配模板语法灵活性特意做的设计。在Vue模板里用:prop绑定值时,支持两种写法:直接传值,或者传一个能返回对应值的函数(常见于动态计算、列表渲染这类场景)。为了让TypeScript兼容这种语法,Vue的类型定义会自动给每个Props的类型加上函数返回值的兼容——也就是把原本的T扩展成T | (() => T)。
所以你传入() => number[]不会报错,但如果函数返回string[]就会触发类型错误,本质是TS在检查函数返回值是否匹配原Props类型,只是允许了函数作为传入形式。
怎么禁用这个特性
如果不需要这种兼容逻辑,可以通过以下两种方式解决:
1. 直接用Exclude排除函数类型
在子组件定义Props时,手动用TypeScript的Exclude工具类型去掉函数类型:
<script setup lang="ts"> defineProps<{ isTsError: Exclude<number[], () => number[]> }>() </script>
2. 封装严格类型的Props定义工具
可以写一个全局工具函数,强制Props只接受原始类型,拒绝函数传入:
// src/utils/defineStrictProps.ts import { defineProps } from 'vue' // 排除所有函数类型 type StrictProp<T> = Exclude<T, () => unknown> export function defineStrictProps<T extends Record<string, unknown>>() { return defineProps<T>() as { [K in keyof T]: StrictProp<T[K]> } }
之后在组件里替换defineProps使用:
<script setup lang="ts"> import { defineStrictProps } from '@/utils/defineStrictProps' defineStrictProps<{ isTsError: number[] }>() </script>
额外提醒
禁用这个特性后,模板里原本写:prop="() => someValue"的地方会报错,建议改成直接传值或者用computed包裹。比如用Pinia getter时,直接传store.someGetter或者computed(() => store.someGetter),不要把getter函数本身传进去,这样既符合类型要求,也能避免潜在的bug。
内容的提问来源于stack exchange,提问作者FrozenKiwi
相关产品推荐
相关产品推荐

