typescript深入理解系列之泛型: 表单填写

写在最前:笔者从去年就开始接触学习ts,但是看了几次文档都朦朦的,所以本系列旨在分享学习ts路上一些较为深入的理解(结合一个实际例子去讲解)

给大家举个很常见的例子,表单填写,很常见吧。

先来段代码:

// 首先声明表单对象的类型interface, 有两个字段,证件号和证件类型, 其中证件号为number类型,证件类型声明了一个证件类型的枚举类型
interface Form {
  idNumber: number | undefined;
  identity: Identity;
}

// 声明证件类型的枚举类型, 有两个值,一个身份证,一个其他
enum Identity {
  idCard = '身份证',
  other = '其他',
}

// 现在来声明对单对象
const form: Form = {
  idNumber: undefined,
  identity: Identity.idCard // 这个一般是Select下拉框嘛,可以给个默认的身份证
}

复制代码

到这里我们就声明完我们的表单对象了,接下来,表单最重要的是什么呢,修改嘛。所以我们声明一个统一的修改表单对象的函数,这样的一个函数,需要的就是key和value了嘛

function changeValue(key, value) {
    form[key] = value;
}
复制代码

很简单对吧,现在我们给他声明类型, 函数的声明需要啥呢,入参和反参嘛。由于这里我们没有反参,就不需要声明啦,会自动推断为void的。

入参有两个,先声明第一个:

  • key, 这个key就是Form类型的key嘛, 很容易联想到 使用关键字 keyof ,所以: key: keyof Form
  • value, 这个可能有些人不知道了,虽然没有关键字 valueOf, 但是可以取巧,对象[key]不就是value嘛,所以: value: Form[keyof Form]

所以写完的函数如下,这时候开始报错了

function changeValue(key: keyof Form, value: Form[keyof Form]) {
    form[key] = value; // Type 'number | Identity | undefined' is not assignable to type 'never'.
}
复制代码

这句话是说我们的 Type ‘number | Identity | undefined’ 不能分配给 never类型

很明显,Type ‘number | Identity | undefined’就是我们value的类型了,ts很简单的,全部联合起来就是你value的类型了嘛, 那么never是哪来的?

这里先说结论,当联合类型赋值给对象时,对象的value需要有共同的类型才可以赋值,不然ts无法识别到底是赋给谁的值。

所以问题在哪呢?问题就在于ts不能知道你给的key和value是配对上的,例如你把证件号赋值给证件类型了,谁知道呢? 所以我们需要明确配对上,这时候就需要泛型了。
泛型是什么呢?我相信大家都有一些自己的理解,毕竟官网文档都没给出具体的名词解释。

看代码来加深一下理解吧。

function changeValue<T extends keyof Form>(key: T, value: Form[T]) {
    form[key] = value; 
}
复制代码

从这份代码可以看出,我们声明了一个泛型,并限制为Form的key的类型,并且声明key为这个类型,value为这个key对应上的值,这样不就对应上了嘛。

需要注意的是,如果这个泛型不继承自 keyof Form 就无法限制T的类型了,所以form[key]就不对了。

结论:泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。从这个例子中可以看出,不预先制定,有时候是为了更好地具体指定类型

完整代码请看:完整代码

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享