Vue 3 与 TypeScript 进阶:给 props、emits 与插槽写类型

test12026-10-174 次阅读

为什么要在组件里写类型

Vue 3 的 script setup 配合 TypeScript,能让父组件传参、子组件回调和插槽数据在编译期就被检查。相比运行时校验,类型错误在写代码时就暴露,重构也更安全。

用泛型给 props 上类型

<script setup lang="ts" generic="T">
const props = defineProps<{
  list: T[];
  selectedId?: string;
  loading?: boolean;
}>();

const emit = defineEmits<{
  (e: 'select', id: string): void;
  (e: 'load-more'): void;
}>();
</script>

defineProps 直接吃泛型参数,T 由父组件传入时自动推断,列表项的类型一路透传下来。

类型安全的 emits

function onPick(id: string) {
  emit('select', id);
}

// 错误用法会在编译期报错:参数数量或类型不匹配
// emit('select'); // TS 错误

把 emits 写成函数签名形式,调用时参数个数和类型都会被检查,漏传或传错类型都过不了编译。

给具名插槽的 props 写类型

<template>
  <ul>
    <li v-for="item in list" :key="item.id">
      <slot name="row" :item="item" :index="list.indexOf(item)">
        {{ item.label }}
      </slot>
    </li>
  </ul>
</template>

<!-- 父组件使用,row 插槽的 item 自动带类型 -->
<MyList :list="data" v-slot:row="{ item }">
  <span>{{ item.label }}</span>
</MyList>

工程建议

  • 组件对外暴露的 props 和 emits 都写类型,内部局部变量尽量交给类型推断。
  • 复杂对象用 interface 单独定义,避免在 defineProps 里内联过长结构。
  • 插槽作用域数据也要标类型,否则父组件拿到的 item 会变成 any。
  • 开启 vue-tsc 做独立类型检查,把它接进 CI 才不会漏掉模板里的类型错误。
T

test1

文章作者

为什么要在组件里写类型 Vue 3 的 script setup 配合 TypeScript,能让父组件传参、子组件回...

分类
技术
发布时间
2026-10-17
字数
约 1183 字
阅读
4 次