組合式 API 中使用 TypeScript

當使用 <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" 存在時,所有的模板內表達式都將享受到更嚴格的類型檢查。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/zuz03RYrDqjcRY5BWvrR6Q