如何在Vue 3项目中使用TypeScript?

Vue 3配上TypeScript,那真是天生一对。Composition API的设计思路,跟用TS写逻辑简直是严丝合缝。今天咱不扯理论,就说说实际写代码时,那些真正有用的小细节。

<script setup>语法糖,现在是主流写法了。你只需要在script标签上加个lang="ts"setup属性,门就开了。定义props得用defineProps这个编译器宏,它的参数直接就是一个类型声明:

<script setup lang="ts">
interface Props {
  title: string;
  count?: number;
}

const props = defineProps<Props>();
</script>

看,多直接。连默认值都能通过withDefaults这个辅助宏来搞定:

const props = withDefaults(defineProps<Props>(), {
  count: 0
});

事件定义用defineEmits,也可以用类型字面量来声明,智能提示一下就有了:

const emit = defineEmits<{
  (e: 'update:title', value: string): void;
  (e: 'confirm'): void;
}>();

setup里写响应式数据,refreactive的类型处理有点小区别。ref推断类型很聪明,你给个初始值它就明白了:

const count = ref(0); // 自动推断为 Ref<number>

但如果你声明的时候不给值,或者值可能为null,就得显式传个泛型参数:

const user = ref<User | null>(null);

reactive的时候,它会对整个对象进行“深度响应式”包装,类型推断一般很准,但你最好也给它约束一个接口:

interface FormState {
  name: string;
  age: number;
}
const form = reactive<FormState>({
  name: '',
  age: 18
});

计算属性computed的类型通常自动从返回值推导出来,很省心。但如果你写的计算属性逻辑分支复杂,手动标注一下返回类型会更稳妥。

在Vue组件里引用一个DOM元素,用ref配合类型标注。这跟React里的useRef很像:

const inputEl = ref<HTMLInputElement | null>(null);

模板ref数组的类型稍微麻烦点,但你把它声明为(Element | ComponentPublicInstance)[]基本就能覆盖大多数情况。

用Pinia管理状态,类型支持好得让人感动。定义store时,stategettersactions都能被很好地推断。你几乎不需要额外写类型,但为state定义一个接口会让结构更清晰:

interface UserState {
  list: User[];
}
export const useUserStore = defineStore('user', {
  state: (): UserState => ({ list: [] }),
  getters: {
    userNameList: (state) => state.list.map(u => u.name)
  },
  actions: {
    async fetchUsers() {
      this.list = await api.getUsers();
    }
  }
});

在组件里直接用这个store,userStore.listuserStore.userNameList的类型都是对的,连actions里的this都帮你推断好了。

最后提醒个小坑。有些第三方Vue库如果没提供类型,你可能需要在shims-vue.d.ts里用declare module给它补上。路由和Vue本身的核心类型一般没问题,但自己写的工具函数,记得做好导出和导入的类型声明。

Vue 3 + TS的体验是越用越顺手的,关键在于开始的时候别怕写那两个接口定义。前期多花三十秒,后期能省三十分钟查bug的时间。

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容