TypeScript类型实战--解决Pinia和vueuse使用过程中的类型丢失问题

大家好,我是苏先生,一名热爱钻研、乐于分享的前端工程师,跟大家分享一句我很喜欢的话:人活着,其实就是一种心态,你若觉得快乐,幸福便无处不在

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组件库类型缺失的问题。有知道如何解决的小伙伴评论区留言哦,这个比较简单,笔者就不花篇幅介绍啦

相关推荐
退休倒计时3 小时前
【每日一题】LeetCode 437. 路径总和 III TypeScript
算法·leetcode·typescript
荒诞英雄3 小时前
从 17MB Vendor 大包到按需加载:Vite 多入口 Vue 组件库首屏优化实践
vue.js·vite
jsonbro3 小时前
手把手带你实现发布订阅模式
前端·vue.js·设计模式
Cobyte6 小时前
23.Vue Vapor 组件 attrs 的实现
前端·javascript·vue.js
斯特凡今天也很帅6 小时前
xml页面可以打开,不报错,但是显示数据的地方也不显示,我是怎么解决的
xml·vue.js
柯克七七8 小时前
给老项目加了 TypeScript,本来只想自己爽,结果全公司代码审查标准被我抬高了
前端·vue.js·typescript
自然 醒10 小时前
前端如何实现在线预览office常见文件功能?
前端·vue.js
肉肉不吃 肉10 小时前
前端调试跨域如何解决
前端·vue.js
卓怡学长11 小时前
w268基于springboot + vue 物流系统
java·数据库·vue.js·spring boot·spring·intellij-idea
子兮曰1 天前
TypeScript 7.0 RC 深度解读:Go 重写完成,10 倍提速,编译器的「奇点时刻」
前端·后端·typescript