TypeScript 与 Vue 3:类型安全实践

TypeScript 与 Vue 3:类型安全实践

TypeScript 为 Vue 3 项目提供类型检查,减少运行时错误。这篇说说在 Vue 中用 TypeScript 的常见场景。

Props 类型推导

Vue 3 的 defineProps 能自动推导类型:

<script setup lang="ts">
// 自动推导
const props = defineProps<{
  name: string
  age: number
  email?: string // 可选
}>()

// 使用
console.log(props.name)
</script>

带默认值:

withDefaults(defineProps<{
  name: string
  age?: number
}>(), {
  age: 0
})

组件事件类型

<script setup lang="ts">
const emit = defineEmits<{
  (e: 'update', value: string): void
  (e: 'delete', id: number): void
}>()

emit('update', 'new value')
</script>

ref 类型

// TypeScript 自动推导
const count = ref(0)        // Ref<number>
const name = ref('张三')   // Ref<string>

// 手动指定
const el = ref<HTMLElement | null>(null)
const list = ref<User[]>([])

reactive 类型

// 手动指定类型
const user = reactive<User>({
  name: '张三',
  age: 25
})

泛型组件

有时组件需要处理任意类型的数据:

<script setup lang="ts" generic="T">
defineProps<{
  items: T[]
  selected: T
}>()
</script>

使用:

<ItemList :items="stringList" :selected="selectedString" />
<ItemList :items="numberList" :selected="selectedNumber" />

常用类型定义

// 接口
interface User {
  id: number
  name: string
  email: string
}

// 类型别名
type Status = 'pending' | 'success' | 'error'

// 枚举
enum Gender {
  Male,
  Female
}

// 联合类型
type ID = string | number

常见错误处理

类型守卫

function isUser(obj: unknown): obj is User {
  return typeof obj === 'object' && obj !== null && 'name' in obj
}

if (isUser(data)) {
  console.log(data.name)
}

非空断言

确定值存在时用 !

const el = document.getElementById('app')
el!.style.color = 'red'

类型收窄

function handleClick(id: string | number) {
  if (typeof id === 'string') {
    console.log(id.toUpperCase())
  } else {
    console.log(id.toFixed(2))
  }
}

Pinia 中使用 TypeScript

import { defineStore } from 'pinia'

interface UserState {
  name: string
  age: number
}

export const useUserStore = defineStore('user', {
  state: (): UserState => ({
    name: '',
    age: 0
  }),

  getters: {
    isAdult: (state): boolean => state.age >= 18
  },

  actions: {
    setUser(name: string, age: number) {
      this.name = name
      this.age = age
    }
  }
})

总结

  • defineProps<{ ... }>() 自动推导 props 类型
  • defineEmits<{ ... }>() 定义带类型的事件
  • ref<T>()reactive<T>() 指定类型
  • TypeScript 让代码更健壮,IDE 提示更准确

进阶技巧阶段结束,下篇开始项目实战阶段。

最后更新 4/30/2026, 8:57:45 AM