vue 中的ts类型限制
props 类型定义设置了必填,使用时仍然显示类型可能为 undefined
vue
<script setup lang="ts">
import type { PropType } from 'vue'
interface TFormData {
name: string
price: number
services: string[]
}
const formProps = {
formData: {
type: Object as PropType<TFormData>,
required: true,
},
submitText: {
type: String,
default: '提交',
},
loading: {
type: Boolean,
default: false,
},
}
defineProps(formProps)
</script>
<template>
<ElCheckboxGroup v-model="formData.services">
<ElCheckbox
v-for="(s, idx) in services"
:key="idx"
:label="s"
>
{{ s }}
</ElCheckbox>
</ElCheckboxGroup>
<ElInput v-model="formData.name" placeholder="请输入商品名称" />
<ElInputNumber v-model="formData.price" />
</template>
ts
const propsType = {
age: {
type: Number,
required: true
}
}
export default deineComponent({
name: 'HelloWorld',
props: PropsType,
mounted() {
this.age // 类型为number || undefined
}
})
原因
PropsOptions
继承只读类型的ComponentPropsOptions
,- 而
ts
中required:true
是被认为在这个对象上是必须的,所以会被消除掉。
vue源代码 🔗
解决方法:在定义 props
类型后加上 as const
断言
ts
export const formProps = {
formData: {
type: Object as PropType<TFormData>,
required: true,
},
submitText: {
type: String,
default: '提交',
},
loading: {
type: Boolean,
default: false,
},
} as const
const props = defineProps(formProps)
给自定义vue组件标注ts类型
我们需要为一个子组件添加一个模板 ref,以便调用它公开的方法。比如,我们有一个 MyModal 子组件,它有一个打开模态框的方法
vue
<!-- MyModal.vue -->
<script setup lang="ts">
import { ref } from 'vue'
const isContentShown = ref(false)
const open = () => (isContentShown.value = true)
defineExpose({ open })
</script>
为了获取 MyModal
的类型,我们首先需要通过 typeof
得到其类型,再使用 TypeScript
内置的 InstanceType
工具类型来获取其实例类型:
vue
<!-- Parent.vue -->
<script setup lang="ts">
import MyModal from './MyModal.vue'
const modal = ref<InstanceType<typeof MyModal> | null>(null)
const openModal = () => modal.value?.open()
</script>
为事件处理函数标注类型
在处理原生 DOM
事件时,应该给事件处理函数的参数正确地标注类型:
vue
<script setup lang="ts">
const handleChange = (event) => {
// 当没有类型标注时, `event` 被隐式地标注为 `any` 类型
console.log(event.target.value)
}
</script>
<template>
<input type="text" @change="handleChange">
</template>
- 上面的代码会在
tsconfig.json
中配置了 "strict": true 或 "noImplicitAny": true 时报出一个 TS 错误。 - 因此,我们要给
event
参数标注类型, 在使用时,可能还需要显式地强制转换event
上的属性
vue
<script setup lang="ts">
const handleChange = (event: Event) => {
console.log((event.target as HTMLInputElement).value)
}
</script>
<template>
<input type="text" @change="handleChange">
</template>