大家好,我是苏先生,一名热爱钻研、乐于分享的前端工程师,跟大家分享一句我很喜欢的话:人活着,其实就是一种心态,你若觉得快乐,幸福便无处不在
github与好文
前言
最近在开发新的h5项目,也没来得及更新TypeScript类型体操系列
就简单分享下在这个项目中使用到的TypeScript的地方
在Pinia中使用
基础的数据类型是可以被自动推导出来的,比如下边这种
ts
const useStore = defineStore('test', {
state() {
return {
loading: false,
};
},
actions: {
updateLoading(loading: boolean) {
this.loading = loading;
},
},
persist: {
paths: ['answers'],
},
});
对于loading属性而言,其类型是string也好,number也好,boolean也罢,都是可以在页面中直接被推断使用的
但如果你和我一样,需要定义一个由对象组成的数组类型时,就会有问题了,如下,我需要存一个answers数据,它记录了每一个步骤下用户的选中信息
ts
const useStore = defineStore('test', {
state() {
return {
answers: [],
};
},
actions: {
updateLoading(answer: { id: string; name: string }) {
this.answers.push(answer);
},
},
});
此时this.answers.push(answer)会报错
为此,我们需要显示的为其指定类型,对于Pinia的defineStore函数,它提供了对应的泛型参数。如下,利用第二个泛型参数指定answers的具体类型即可
但此时又会产生新的问题,即actions.updateLoading丢失
为此,还需要为updateLoading显示的指定类型
在上述的例子中的第三个泛型参数,是笔者设置到公共的辅助类型,如下
ts
export type AnyObj = {
[o: string]: any;
};
在vueuse中使用
相信大家一般都不会直接使用useFetch,用它的createFetch自己简单封一层才是较为明智的选择
ts
createFetch({
baseUrl: 'https://www.jianshu.com',
options: {
async beforeFetch({ options }) {
options.headers = {
...options.headers,
...
};
return { options };
},
},
})
如果只是这样的话,是没啥子问题的,因为ts会自动帮我们推断出正确的类型。但经常我们需要根据环境变量做些特定的事情,比如删除或新增某个属性,这就导致我们没法直接在函数内传递参数,而是需要将参数提取出来
ts
const config = {
baseUrl: 'https://www.jianshu.com',
options: {
async beforeFetch({ options }) {
options.headers = {
...options.headers,
Accept: 'application/json',
};
return { options };
},
},
};
此时,beforeFetch的参数类型丢失
为了解决这个问题,我们需要取到createFetch的参数类型,相信看过笔者之前文章的同学已经知道该用谁了,没错,就是Parameters,由于函数的参数是一个数组类型,所以我们取到后,取数组的第一个,另外,这个参数也是可选的,为了避免使用可选链影响美观,咱们使用Required再强制转换下就好啦。(关于这两个工具类型的实现原理,可以看笔者之前的文章哦🥰)
ts
Required<Parameters<typeof createFetch>>[0]
总结
本文,笔者简单总结了在vue+ts+pinia+vueUse项目中使用ts解决类型丢失的问题。其实除了这些还有别的,比如使用的vant组件库类型缺失的问题。有知道如何解决的小伙伴评论区留言哦,这个比较简单,笔者就不花篇幅介绍啦