变量类型汇总
类型 | 描述 |
number | 任意数字 |
string | 任意字符串 |
boolean | 布尔值(true或false) |
字面量 | 直接限制变量的值(类似于常量,很少使用) |
any | 任意类型 |
unknown | 类型安全的any |
void | 空值(undefined) |
never | 不能是任何值(连空值都不是) |
object | 任意JS对象 |
array | 任意JS数组 |
tuple | 元组,即固定长度数组,TS新增类型 |
enum | 枚举,TS新增类型 |
字面量
直接使用字面量进行类型声明:
let a:10
a=11 //报错,a的值固定是10,不能修改,类似于常量
但这样的用法其实很少,更多地是使用字面量来限制变量的取值范围或者类型范围,使用“|”来区分不同的值或变量类型:
//限定值的范围,b可以取值"male"或"female"
let b:"male"|"female";
b="male";
b="female";
//限定值的类型,c可以是boolean类型,也可以是string类型
let c:boolean|string
c=true
c='hello'
any
一个变量设置类型为any后,相当于对该变量关闭了TS的类型检测,此时变量可以赋予任何类型的值。换句话说让这个变量变成跟在JS中一样了。any是不安全的,在实际应用中不建议使用any。需要注意的是,如果在声明时不赋值,也不指定类型,那么TS会默认它为any类型。
let d:any //显式any
let d //隐式any
unknown
难免遇到不知道变量类型的情况,这时更推荐用unknown而不是any。unknown类型的变量也可以是任意类型的值,但unknown会比any更安全。any类型的变量可以赋值给任意其他类型的变量,并使被赋值的变量类型也变成any,即被赋值的变量也会失去TS的类型检测。
let s:string //s声明时的变量类型是string
let d:any
d='hello' //这里d的变量类型使any,不是string
s=d //这里s的变量类型也会变成any
与之不同,unknown是不可以赋值给其他类型变量的
let e:unknown
e='hello' //e是unknown类型,不是string类型
let s:string
s=e //会报错,unknown类型的变量不能赋值给string类型的变量
如果想将unknown类型的值赋值给其他变量,可以采用if判断,数据类型符合再赋值:
let e:unknown
e='hello' //e是unknown类型,不是string类型
let s:string
if(typeof e==="string"){
s=e;
}
或者采用类型断言,告诉编译器unknown变量存储的值的类型是什么:
let e:unknown
e='hello' //e是unknown类型,不是string类型
let s:string
//写法一:变量 as 类型
s=e as string
//写法二:<类型> 变量
s=<string> e
void和never
多用于函数的返回值。void用于没有返回值的函数。never表示什么都没有,连空值都没有,多用于报错等没有返回结果的函数。
object
JS中一切都是对象,实际上我们定义对象是为了定义对象的属性,而不是它“是不是一个对象”。
let b:object //可以,但意义不大
let b:{name:string}; //限定对象中包含的属性,赋值时的结构必须和声明时一模一样
b={name:'小明'}; //正确,对象赋值时结构和声明时相同
b={name:'小明',age=18}; //报错,声明时没有age属性
let b:{name:string,age?:number}; //属性后加"?"表示可选属性
b={name:'小明',age=18}; //正确,对象赋值时结构和声明时相同
b={name:'小明'}; //正确,age为可选属性,可以不添加
let b:{name:string,[propName:string]:number}; //[]表示任意类型的属性,propName是属性名,属性名的类型是string,属性的类型是number
let b={name:'小明',age:18,height:160];//name是必须有的属性,除此之外可以添加任意数量的属性,但类型都必须是number
比较特殊的是对函数对象的声明,形式类似于箭头函数:
let d=(d1:number,d2:number)=>number;//函数d有两个参数d1和d2,并且都是number类型,返回值也是number类型
d=function(d1:number,d2:number):number{
return 10;
}//函数的参数类型、数量、返回值类型都必须和上述完全一致
array
JS中数组元素的类型可以不相同,但在实际应用中数组中元素的类型往往是相同的,所以TS中在声明数组时需要指定元素的类型。
//声明数组a,其元素都是string类型
//方式一:类型[]
let a:string[];
//方式二:<Array>类型
let a:<Array>string;
tuple
元组,即长度固定的数组,TS的新增类型,在JS中没有。因为长度固定,所以通常存储效率会更高。在声明时需要指定每一个元素的类型。一般不会太长,太长就用数组了。
//声明元组a,其中有三个元素,类型分别是string、string、number,元素的数量和类型的顺序都是固定的,在赋值时必须一致,否则会报错
let a:[string,strinng,number]
a=['hello','world',10]
enum
枚举,适用场景是变量的值在一定范围内,从某几个固定值中选。类似于定义一个新的类。
//枚举对象包含两个属性Male和Female,其值分别为0和1
enum Gender{
Male=0,
Female=1
}
let i:{name:string,gender:Gender}//gender属性的值要从enum对象Gender的属性值中选
i={name:'小明',gender:Gender.Male}//属性gender的值是Gender中的Male值
//实际存储0和1要比存储字符串"Male"和"Female"效率更高,用这种方式实际存取的还是0和1,但可以让写代码的人看明白是什么含义
&连接符
表示两种属性都具备:
let j:{age:number}&{name:string}//表示j必须同时具备age和name属性,并指定了属性的数据类型
类型的别名
可以为类型指定一个别名,例如:
type myType=string;//为string类型起一个别名myTpe,后面可以用myTyepe代替string
let a:myType;
但这样做没什么意义,实际比较常用的是简化比较长的类型/值的使用:
type myType1=1|2|3|4|5
let a1:myType1
a1=1 //正确,在myType涵盖的值以内
a1=9 //错误,不再myType涵盖的值以内
type myType2=string|number
let a2:myType2
a1='hello' //正确,在myType涵盖的类型以内
a2=false //错误,不在myType涵盖的类型以内