ts 里面的类型有不少,我们来逐一了解。
首先,我们来看下变量的类型:
1,number、string、boolean
number 类型,里面只能放 number。同样的, string 类型,里面也只能放 string。
boolean 类型只有两个值,一个 true,一个 false。
2,null、undefined
null 类型里面,就只有唯一的一种值,就是 null。
undefined 类型也是一样,也只有唯一的一种值,就是 undefined。
所以你可以认为,它既是一个类型,也是一个值。
3,void
void,翻译成中文,就是“空”。
简单的来说,void 就是没有东西。它和 null、undefined 是不一样的。
void 一般情况下,是用于返回值。意思就是这个函数没有返回值。
当然,你把它用在变量里面也能用,但是会有点奇怪。
所以 void 这个空,用于变量类型,并没有什么实在的意义,因为它就是不允许赋值。所以没有用。
4,enum
enum 全称是 enumerate。翻译成中文,就是“枚举”,它的意思就是,列举所有的东西。
枚举,说的简单点,就是世界上有很多值,但只有那么几种可能。
比如,性别,就只有男和女。
星期,就只有星期一到星期日,不可能有之外的值。
所以,枚举指的是有限的可能性。
说白了,就是在定义阶段,就已经把它所有可能的值,全给你列举出来,没有别的选择了。
大写是个人习惯,一般情况下,枚举它的语义,其实来讲,代表的是不会变的,类似于常量,语义代表着不可修改的含义。
5,any
any 就是变体变量。说白了,就是没有固定的类型,可以是任何类型。
js 里面原本的变量,它就是变体变量。
所以,any 的意思,就是变量 a 里面允许存任何类型的东西。
其实,不仅变量有类型,数组也有类型:
比如,当我们 let a:Array 的时候,我们要求变量 a 必须是个数组。
但是我们这样写,很明显,编译的时候它给报错了。
因为,你并没有告诉它,你的这个 Array 是个什么类型的数组。
所以我们在声明数组的时候,也要加上类型。
这个意思就是告诉它,a 这个数组是装字符串的。可以看到,我们赋值后,不会报错。
那么如果我们加个数字进去,会怎么样呢?
它就会报错。
但是,如果每次我们都写 let a:Array<string> 会很麻烦。
所以字符串数组可以简写: let a:string[]。
let a:Array<string>
等价于:
let a:string[]
let arr = [12, 5, 8]
等价于:
let arr:number[] = [12, 5, 8]
let arr = [12, 'abc', false]
等价于:
let arr:any[] = [12, 'abc', false]
然后我们在来看下对象类型:
对象类型也称为复合类型。
这个意思是说,a只能是个对象,并且a里面,必须得有 x 和 y,并且都是数字。
那如果我们在赋值的时候少了一个 y,或者多加上了一个 z 呢?
所以我们可以看到,ts 的规范是很严格的,连它里面东西的个数,和类型,都给你定死了。
一个不能多,也一个不能少,类型还必须都得匹配到。
但是我们实际上开发的时候,是不确定一个对象里面字段的,那么应该怎么办?
我们可以加上一个 '?' 符号,它的意思是可有可无。
这里的意思是说,a 只能是个对象,并且 a 里面,必须得有 x 和 y,并且都是数字。
但是 z 可有可无,可能有,也可能没有。
其实我们在项目中,操作最多的数据可能就是对象了,而且它们的类型也都大同小异。
那么如果我们每一个都要这么写,就会很麻烦。所以我们能不能自己来定义一个类型,然后共用呢?
答案是可以的。type 这个关键字就是专门用来定义类型的。
type:
这里的意思是,我定义了一个类型 C,它里面必须得有 name 和 age,并且 name 是字符串,age 是数字。
这时候我又声明了一个变量 user,那么我就让 user 的类型和 C 保持一致。
所以 type 这个关键字,可以帮助我们来声明一个全新的类型。
这样的话,我们一些比较常用的东西就不用老去写了。
联合类型:
联合类型的意思是,有可能是这种,或者那种类型的值,是有选择的。
这个 a 既可以是个数字,也可以是个字符串。
可以看到,编译不会报错。
然后,我们来写个三目,根据 b 的类型,来决定 a 的值。
可以看到,编译也不会报错。
然后我们来更改一个值,将 'abc' 替换为 false:
再编译就会报错了,说 false 不是 string 和 number,是不能放进去的。
是不是觉得 ts 特别的智能?其实这也是 ts 的一个特点,类型推测。
说白了,就是变量的类型,能够根据初始化的值推测出来。
然后我们再来看下函数的类型:
函数的类型又分为两种,一个是参数的类型,一个是返回值的类型。
其实函数类型声明的时候,它会做一个签名检查,也就是函数签名:
所谓的函数签名,说白了,就是这个函数接收哪些参数,每个参数什么类型,哪些是可选的,返回什么值。
1,参数类型
可以看到,如果参数的类型不对,它就会报错。
其实参数不光有类型,并且它的数量还要一致,不能少一个,也不能多一个:
可以看到,参数数量不吻合,实参跟形参对不上,它也会报错。
那么我们在实际开发中,封装一些公用的方法,它的参数可能是1个,也可能是2个,这个应该怎么做呢?
我们可以用 '?' 符号来做,也就是可选参数。
2,返回值
我们可以规定一个函数的返回值,如果返回的是其他类型,就会报错。
其实还有一种判断的情况,就是有可能符合要求,也可能不符合要求。
看完了函数签名之后,是不是觉得每个函数都这么写,有些麻烦?
我们可以来做个对比。先来看看我们平时 js 的写法。
相信这样的写法,你已经看过很多次了。
其实这样的写法也很麻烦。每个参数,我们也是要写注释的。
而且最重要的一点,写了注释,别人就一定会遵守吗?
那么如果使用 ts 来写呢?
上面的 type callback 是我们自己定义的类型。
刚接触函数签名,这里可能会有点混淆,其实很简单。
你可以把它理解为,我们平时写的箭头函数。
就是这样的:(number, number) => number
然后我们再来看一个例子就完全懂了,比如我们自己来定义一个 ajax:
一眼看过去,是不是有种掀桌的冲动?这都什么玩意儿?
其实刚开始大家都是这样的,一个很简单的函数,弄的这么复杂。
但是一旦用到了项目中,你就会发现,真香!
然后我们一起来解析下:
第一个参数 url:只能传 string 类型。
第二个参数 success 是一个回调函数,它有2个参数,一个 res 是 string 类型,一个 code 是 number 类型。并且要求你的返回值类型是 void,也就是没有任何返回值。
第三个参数 err 也是一个回调函数,但它只能接收一个参数 code,为 number 类型。并且也没有任何返回值。
其实 success:(res:string, code:number)=>void 就是函数签名。
意思就是你都接收什么类型的参数,有几个,返回值是什么。