# 类型不会复用

在日常开发中,一般我们对于每个接口都要定义好请求参数的类型和返回参数的类型。而对于一些比较常见的功能,我们一般会有固定的参数和一些固定的返回字段

例如列表接口,我们一定会带上page和rows,这个时候我们就可以写一个基础的列表请求类型如:

interface ReqPage {
    current?:number;
    size?:number;
}

另外对象类型也有喜欢用type定义的小伙伴,那么对于type我们可以复用,但是形式上稍微有点不同,还是上面例子

type ReqPage = { current?:number; size?:number };

type UserListParams = {
    name: string;
    id: string | number;
} & ReqPage

对于返回参数的类型定义也一样,后端接口一般有几个字段例如createTime,updateTime等必定返回的,我们可以提前定义一个基类用于其他返回类型去继承复用

# 不会使用工具类型

Typescript内部提供了很多工具类型如:Partial、Pick、Exclude、Omit等

举个在日常工作中经常遇到的例子,还是后台管理系统中常见的列表功能。一般我们的表格会有一些搜索字段,这个时候我们就可以用上我们的工具类型了

// 假设我们现在有一个用户列表,它的返回格式如下
interface ResUser {
    name: string;
    id: string | number;
    age: number
    grade: number;
}

// 如果我们将name作为搜索条件,那么你的请求参数类型应该怎么定义呢?我们可以使用工具类:Pick 或者 Exclude
type ReqUser = Pick<ResUser, 'name'> & ReqPage;

// 如果搜索条件的字段较多时候我们就可以考虑使用Exclude方法

个人认为使用工具类有两个好处

  • 将两个有关联的类型关联起来,而不是凭空创造一个新的类型。让团队中的其他人知道他们是属于一个功能模块
  • 增加复用性,而不是单纯的 copy yourself

# 不会使用泛型

还是上面列表接口的例子,我们一般列表分页接口会包含几个通用的字段,例如records-当前页数的数据,total-总页数,pages-总页数等等。但是对于不同的接口我们所需要定义的类型肯定不一样的,就是说records对应的类型肯定是不同的。

这时候就有小伙伴想起上面的复用了。但是除此之外我们还有更好的方法实现--就是泛型

// 分页相应参数
interface ResPage<T> {
    records: T[];
    current: number;
    size: number;
    total: number;
}

通过泛型我们就可以很好的定义。我个人认为泛型就是一个'类型变量',它在代码编写阶段可以代表多种类型,在实际使用时再确定具体类型。在看下面的例子:

function handle<T>(input: T): T {}

const author = 'test'; // 使用 const生命,被推到位tst

let authorAge = 18;

handle(author);
handle(authorAge);

泛型对于我们开发中写一些公用的基础类型、公用方法、公用hooks很有用,大家可以多学习一下。

# 图方便乱用any

相信AnyScript的名号大家都嗤之以鼻,但是在实际开发中,还是有很多场景会因为一时的方便,而是用any跳过校验

// 片段1
const onChange = (value: any) => {
    emit('change', value);
}

// 片段2
let provinceCode: any = '';

上面这两段代码都是我在我们团队的项目中找出来的,类似的代码还有很多。

其实我觉得用any偷懒这个问题,并不是技术水平上的问题而是自己的态度问题。像上面例子中的provinceCode,我们有必要用any去定义类型吗?

我们应该在每次想使用any之前多问自己一下,这个类型真的无法定义吗?能用unknown代替吗?我相信就会有结果。

# 不会使用框架或组件库里的类型

我的项目中常用到的是vue3,element-plus和uni-app等

举个最简单的例子,我发现有的开发小伙伴居然不知道vue3里面的ref,computed是可以定义类型的~~

// ref
const userName = ref<string>('');

// computed
const userName = computed<string>(() => {
    return 'haha'
})

样的对element-plus,使用的时候可以多看下文档,看下怎么定义类型:

<script lang="ts" setup>
    import {reactive, ref} from 'vue';
    import type { ComponentSize, formInstance, FormRules } from 'element-plus';

    interface RuleForm {
        name: string;
        region: string;
        count: string;
        date1: string;
        data2: string;
        delivery: boolean;
    }
    const formSize = ref<ComponentSize>('default');
</script>

对于一些第三方库文档上没有类型定义,可以自己翻查一下node_modules/types或者对应第三方库的d.ts文件

# 不会使用枚举和字面量类型

在项目中,我们可以定义一些枚举,然后在定义新的类型时,可以使用这些枚举使我们的类型更加准确:

enum SideDeptFlagEnum {
    INSIDE = 1; // 内部单位
    OUTSIDE = 2; // 外部单位
}

interface Dept {
    name: string;
    flag: SideDeptFlagEnum
}

这样子定义的话,我们在赋值的时候就会获得准确的提示。如果我们定义成普通的number类型的话,则无法校验是否1或者2.当然我们也可以定义成字面量类型~~