当使用 <script setup>
时,defineProps()
宏函数支持从它的参数中推导类型:
<script setup lang="ts">
const props = defineProps({
foo: { type: String, required: true },
bar: Number
})
props.foo // string
props.bar // number | undefined
</script>
然而,通过泛型参数来定义 props 的类型通常更直接:
<script setup lang="ts">
const props = defineProps<{
foo: string
bar?: number
}>()
</script>
reactive() 也会隐式地从它的参数中推导类型:
import { reactive } from 'vue'
// 推导得到的类型:{ title: string }
const book = reactive({ title: 'Vue 3 指引' })
要显式地标注一个 reactive 变量的类型,我们可以使用接口:
import { reactive } from 'vue'
interface Book {
title: string
year?: number
}
const book: Book = reactive({ title: 'Vue 3 指引' })
在 <script setup>
中,emit
函数的类型标注也可以通过运行时声明或是类型声明进行:
<script setup lang="ts">
// 运行时
const emit = defineEmits(['change', 'update'])
// 基于类型
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
</script>
ref 会根据初始化时的值推导其类型:
import { ref } from 'vue'
// 推导出的类型:Ref<number>
const year = ref(2020)
// => TS Error: Type 'string' is not assignable to type 'number'.
year.value = '2020'
有时我们可能想为 ref 内的值指定一个更复杂的类型,可以通过使用 Ref 这个类型:
import { ref } from 'vue'
import type { Ref } from 'vue'
const year: Ref<string | number> = ref('2020')
year.value = 2020 // 成功!
computed()
会自动从其计算函数的返回值上推导出类型:
import { ref, computed } from 'vue'
const count = ref(0)
// 推导得到的类型:ComputedRef<number>
const double = computed(() => count.value * 2)
// => TS Error: Property 'split' does not exist on type 'number'
const result = double.value.split('')
你还可以通过泛型参数显式指定类型:
const double = computed<number>(() => {
// 若返回值不是 number 类型则会报错
})
为事件处理函数标注类型,这个 event 参数会隐式地标注为 any 类型。。因此,建议显式地为事件处理函数的参数标注类型。
function handleChange(event: Event) {
console.log((event.target as HTMLInputElement).value)
}
模板引用需要通过一个显式指定的泛型参数和一个初始值 null 来创建:
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const el = ref<HTMLInputElement | null>(null)
onMounted(() => {
el.value?.focus()
})
</script>
<template>
<input ref="el" />
</template>
为组件模板引用标注类型,为了获取 MyModal 的类型,我们首先需要通过 typeof 得到其类型,再使用 TypeScript 内置的 InstanceType 工具类型来获取其实例类型:
<!-- App.vue -->
<script setup lang="ts">
import MyModal from './MyModal.vue'
const modal = ref<InstanceType<typeof MyModal> | null>(null)
const openModal = () => {
modal.value?.open()
}
</script>
<template>
<MyModal ref="modal" />
</template>
为了让 TypeScript 正确地推导出组件选项内的类型,我们需要通过 defineComponent() 这个全局 API 来定义组件:
import { defineComponent } from 'vue'
export default defineComponent({
// 启用了类型推导
props: {
name: String,
msg: { type: String, required: true }
},
data() {
return {
count: 1
}
},
mounted() {
this.name // 类型:string | undefined
this.msg // 类型:string
this.count // 类型:number
}
})
要在单文件组件中使用 TypeScript,需要在 <script>
标签上加上 lang="ts" 的 attribute。当 lang="ts" 存在时,所有的模板内表达式都将享受到更严格的类型检查。