下面给你一份 Vue 3 + TypeScript 下接口 (interface) 使用的详解示例,从基础到进阶,涵盖组件 props、响应式数据、函数类型、泛型以及与 Vue 组合式 API 的结合实践。


1️⃣ 基础接口使用

// 定义一个接口
interface User {
  id: number
  name: string
  age?: number // 可选属性
}

// 使用接口声明变量
const user1: User = {
  id: 1,
  name: 'Alice',
}

// 错误示范:缺少 id
// const user2: User = { name: 'Bob' } // ❌ TS 会报错


2️⃣ 接口与函数类型

interface Greeter {
  (name: string): string
}

const greet: Greeter = (name) => {
  return `Hello, ${name}!`
}

console.log(greet('Alice')) // Hello, Alice!


3️⃣ 接口继承(Extends)

interface Person {
  name: string
  age: number
}

interface Employee extends Person {
  employeeId: string
}

const emp: Employee = {
  name: 'Tom',
  age: 25,
  employeeId: 'E1001'
}


4️⃣ Vue 3 + TypeScript 使用接口示例

4.1 定义 Props 接口

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

// 定义接口
interface User {
  id: number
  name: string
  age?: number
}

// 使用接口定义 props
const props = defineProps<{
  user: User
  showAge?: boolean
}>()
</script>

<template>
  <div>
    <p>名字: {{ props.user.name }}</p>
    <p v-if="props.showAge">年龄: {{ props.user.age }}</p>
  </div>
</template>

✅ 好处:

  1. props 有类型约束
  2. 支持可选属性
  3. 编辑器提示强大

4.2 定义响应式对象

<script lang="ts" setup>
import { reactive } from 'vue'

interface Product {
  id: number
  name: string
  price: number
}

const product = reactive<Product>({
  id: 1,
  name: 'MacBook Pro',
  price: 1999
})

// 修改属性
product.price = 1899
</script>


4.3 接口定义函数参数

interface Calculator {
  (a: number, b: number): number
}

const add: Calculator = (a, b) => a + b
const multiply: Calculator = (a, b) => a * b

在 Vue 事件中使用:

const handleClick = (fn: Calculator) => {
  console.log(fn(2, 3))
}


5️⃣ 接口与泛型结合

interface ApiResponse<T> {
  code: number
  data: T
  message: string
}

// 示例接口返回 User 数据
const res: ApiResponse<User> = {
  code: 200,
  data: { id: 1, name: 'Alice' },
  message: 'ok'
}

在 Vue 组件中可直接使用泛型:

import { ref } from 'vue'

const response = ref<ApiResponse<User>>({
  code: 0,
  data: { id: 0, name: '' },
  message: ''
})


6️⃣ 高级接口:索引签名 & 交叉类型

6.1 索引签名

interface StringMap {
  [key: string]: string
}

const obj: StringMap = {
  name: 'Alice',
  city: 'Beijing'
}


6.2 交叉类型(组合多个接口)

interface A { a: number }
interface B { b: string }

type C = A & B

const objC: C = { a: 10, b: 'Hello' }


7️⃣ Vue 3 组合式 API 综合示例

<script lang="ts" setup>
import { reactive, ref } from 'vue'

interface Todo {
  id: number
  title: string
  done: boolean
}

const todos = reactive<Todo[]>([
  { id: 1, title: 'Learn Vue 3', done: false },
  { id: 2, title: 'Learn TypeScript', done: true }
])

const newTodo = ref<Todo>({ id: 3, title: 'Write demo', done: false })

const addTodo = () => {
  todos.push({ ...newTodo.value })
  newTodo.value.title = ''
}

const toggleTodo = (todo: Todo) => {
  todo.done = !todo.done
}
</script>

<template>
  <div>
    <ul>
      <li v-for="todo in todos" :key="todo.id">
        <input type="checkbox" v-model="todo.done" @change="toggleTodo(todo)" />
        {{ todo.title }} - {{ todo.done ? '完成' : '未完成' }}
      </li>
    </ul>

    <input v-model="newTodo.title" placeholder="新任务" />
    <button @click="addTodo">添加</button>
  </div>
</template>

✅ 特点:

  1. todo 类型强约束
  2. 新增、修改都自动提示类型
  3. Vue 响应式和 TS 类型结合完美

8️⃣ 总结

  1. interface vs type
    • interface 可以声明对象、函数类型、继承、合并声明
    • type 更适合联合类型、交叉类型、基本类型别名
  2. Vue 3 + TS 最常用场景:
    • defineProps<Interface>()
    • reactive<Interface>() / ref<Interface>()
    • 函数参数类型
    • API 返回值泛型类型
  3. 优势:
    • 代码可维护性强
    • 编辑器提示完善
    • 组件 props / 事件 /状态都有类型安全