如何在 Vue3 中更好地使用 Typescript

www.jswusn.com Other 2025-04-03 17:04:02 18次浏览

TypeScript 为 Vue 应用带来了强大的类型系统支持,Vue3 更是从底层开始使用 TypeScript 编写。本文将介绍 Vue3 中自带的 TypeScript 类型工具及其最佳实践,通过示例代码帮助开发者编写类型安全的 Vue 组件

一、基础组件类型

1.1 组件定义

使用 defineComponent 创建类型安全的组件:

import { defineComponent } from 'vue'

// 推荐使用 defineComponent 获得完整的类型推断
export default defineComponent({
  setup() {
    //自动推断出返回对象的类型
    return {
      message:'hello Vue3'
    }
  }
})

1.2 Props 类型声明

使用 PropType 处理复杂类型:

import { defineComponent,PropType } from 'vue'

interface User{
  id:number
  name:string
  age?:number
}

export default  defineComponent({
  props:{
    // 基础类型
    title:{
      type:String,
      required:true
    },
    // 复杂对象类型
    userInfo:{
      tyoe Object as PorpType<User>,
      required:true
    },
    //数组类型
    tags:{
      type:Array as PropType<string[]>,
      default:()=>[]
    }
  },
  setup(props){
    //自动推断出 props.title 为 string
    console.log(props.title.toUpperCase())

    //正确访问 User 类型的属性
    console.log(props.userInfo.name)
  }
})

二、组合式 API 类型

2.1 Ref 类型

import { ref,Ref } from 'vue'

// 显式指定 Ref 类型(推荐)
const count: Ref<number>=ref(0)

//通过泛型初始化推断
const user = ref<User>({
  id: 1,
  name:'Alice'
})

//自动推断为 Ref<number>
const double = computed(()=> count.value * 2)

2.2 Reactive 类型

import { reactive } from 'vue'

interface Formstate{
  username:string
  password: string
  remember: boolean
}

// 使用接口定义 reactive 类型
const formState = reactive<FormState>({
  username:'',
  password:'',
  remember: false
})

三、组合式函数类型

3.1 自定义 Hook

import { ref, onMounted, Ref } from 'vue'

// 定义返回值类型
interface UseFetchResult<T>{
  data: Ref<T | null> 
  error: Ref<Error | null>
  loading: Ref<boolean>
}

export function useFetch<T>(url: string): UseFetchResult<T>{
  const data = ref<T | null>(null)
  const-error =ref<Error | null>(null)
  const loading = ref(true)

  onMounted(async()=>{
    try {
      const response = await fetch(url)
      data.value = await response.json()
    } catch(e){
      error.value =e as Error
    } finally {
      loading.value = false
    }
  })

  return {data, error, loading}
}

四、组件通信类型

4.1 自定义事件

<script setup lang="ts">
// Child.vue
import { defineComponent } from 'vue'

export default defineComponent({
  emits:{
    // 验证 submit 事件
    submit:(payload:{email:string; password:string })=>{
      return payload.email.includes('@') && payload.password.length >= 6
    }
  },
  setup(props,{emit }){
    const handleSubmit =()=>{
      emit('submit',{
        email:'user@example.com',
        password:'secret'
      })
    }
    return { handleSubmit }
      
  }

})

</script>

// Parent.vue
<template>
  <Child @submit="handleSubmit" />
</template>
<script setup lang="ts">
const handleSubmit =(payload:{ email: string; password: string })=> {
  console.log('Received:', payload)
}

</script>

4.2 模板引用类型

// 引用 DOM 元素
const inputRef = ref<HTMLInputElement | null>(null)

//引用子组件实例
const childComponent = ref<InstanceType<typeof childComponent>| null>(null)

onMounted(()=> {
  inputRef.value?.focus()
  childComponent.value?.someMethod()
})

五、进阶类型技巧

5.1 全局属性扩展

// main.ts
import { createApp } from 'vue'

declare module 'vue'{
  interface ComponentCustomProperties{
    $filters:{
      currency(value:number):string
    }
  }
}

const app = createApp(App)
app.config.globalProperties.$filters = {
  currency(value:number){
    return`$${value.toFixed(2)}`
  }
}

5.2 类型化 Provide/Inject

import {inject, provide } from 'vue'

interface UserContext{
  id: number
  name: string
}
const symbol =Symbol() as InjectionKey<UserContext>

// 父组件
provide(symbol,{
  id: 1,
  name:'Alice
})

// 子组件
const user =inject(symbol)//类型为 Usercontext | undefined


技术分享

苏南名片

  • 联系人:吴经理
  • 电话:152-1887-1916
  • 邮箱:message@jswusn.com
  • 地址:江苏省苏州市相城区

热门文章

Copyright © 2018-2025 jswusn.com 版权所有

技术支持:苏州网站建设  苏ICP备18036849号