Vue中TypeScript的常用标注类型(二)emits、ref和reactive

355 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情

组件 emits 的标注类型

同样的,如果你使用的是<script setup>的形式,emit 函数的类型标注也有运行时声明和类型声明两种:

  • 运行时声明:
<script setup lang="ts">
const emit = defineEmits(['change', 'click'])
</script>
  • 类型声明:
<script setup lang="ts">
// 基于类型
const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'click', value: string): void
}>()
</script>

我们可以看到基于类型的声明可以对触发的事件类型,参数类型,以及返回的类型都可以进行更加细微的控制,对比第一种显然是很全面的。

组件 ref() 的标注类型

当我们不给ref标注任何类型的时候,他会根据初始化的值自动推导类型。

import { ref } from 'vue'

// 自动推导出的类型:Ref<number>
const year = ref('string')

// => TS Error: Type 'number' is not assignable to type 'string'.
year.value = 2022

但是,一般业务下ref的类型可能更为复杂,这时我们就可以通过vue暴露Ref类型来声明它。

import { ref } from 'vue'
import type { Ref } from 'vue'

const num: Ref<string | number> = ref('2020')

num.value = 2020 

当然,也可以使用更为简单的方式,给其传入一个泛型参数,就可覆盖默认的推导行为:

// 得到的类型:Ref<string | number>
const num = ref<string | number>('2020')

num.value = 2020 

注意:如果你给ref指定了泛型参数,却没给初始值的话,那么你将得到一个包含undefined的联合类型:

// 推导得到的类型:Ref<number | undefined>
const num = ref<number>()

组件reactive() 的标注类型

和上两种一样,都具有自动推导类型的能力:

import { reactive } from 'vue'

// 自动推导得到的类型:{ title: string }
const article = reactive({ title: '我是标题' })

相应的,想要更加细微的控制类型的话,也可以进行显示标注:

import { reactive } from 'vue'

interface Article {
  title: string
  num?: number
}

const article: Article = reactive({ title: '我是标题' })

注意:reactive()官方并不推荐使用泛型参数,因为泛型的参数类型与深层次ref解包的返回值不同。