TS的基本类型
number:数字
let num:number=2
string:字符串
let name:string='fcc study ts'
boolean:布尔
const target: boolean = false
数组
这里值得注意:数组的约束 不能这样let arr: []= [1,2,3]写; 只能 let arr: []= [] 或者加类型约束let arr: string[] 这里先不做解释为什么,到后面会详解
数组每一项都是数字 ,一般是使用: number[],也可以使用构造函数的方式: Array<number>,这两种方式是一样的
const arr: number[] = [1,2,3,4]
const arr2:Array<number>=[1,2,3,4]
数组每项都是字符串,: string[]
const arr: string[] = ['1','2','3','4']
const arr2: Array<string> = ['1','2','3','4']
数组每一项是对象 : {}[], 当然如果每个对象里面有些字段需要约束则,需要进行约束, 如每个对象中必须有个uid位置值且是string,: {uid: string}[]
const arr: {uid: string}[] = [{uid: 'jiandidewoniu'}]
const arr2: Array<{uid:string} >= [{uid: 'jiandidewoniu'}]
数组的每一项是一个数组: number[][] = [[1,2],[3,4,],],多维数组就和一维数组一样,嵌套就可以
const arr: number[][] = [[1,2],[3,4,],]
const arr2:Array<Array<number>>=[[1,2],[3,4,],]
如果你使用的是Array<Array<number>>这种方式的这里得注意了,
如果书写代码规范 喜欢在定义的时候打上空格,那就没啥事,那是你习惯很好,
可能就不不会发现这个东西,【Array<Array<number>>=】这里的【>>=】,
如果你不在等号【=】两边加上控制,就会出现问题,可能编译器就会认为你这里既然是大于等于【>=】了,
前面就不需要在加一个大于【>】,虽然运行后没啥问题,但是对于代码规范,还是习惯在等于号两边加上空格更好些【let a: string = 'a'】
数组里面类型不是固定的,则可以这样写,用 “|” 或符号: string[] | number[] | {}[] | [类型1,类型2,...][],这样你这个数组就啥类型都可以了,但是数组中类型只能有一个,要么都是string,要么都是number,要么都是对象,要么都是二维数组,当[][]二维数组,里面没有任何东西时,赋值的时候也只能是空,不然会报错,如果[1,2][]那么二维数组里面每一项都只能是[1,2],且顺序不能变
let arr3: string[] | number[] | boolean[] | [number,string][] = ['1','3','5']
let arr4: string[] | number[] | boolean[] | [number,string][] = [1,3,5]
let arr5: string[] | number[] | boolean[] | [number,string][] = [[1,'2'],[3,'4'],[5,'3']]
let arr6: string[] | number[] | boolean[] | [][] = [[],[],[]]
let arr7: string[] | number[] | boolean[] | [1,2,3][] = [[1,2,3],[1,2,3],[1,2,3]]
对象
object:: object 这样只能约束变量是否是对象,至于对象内容是啥他就不管,只要是对象就像,约束力没那么强
const obj: object = {}
{}: : {对像内容约束},如果{},里面没有约束的化,其实和object 没啥区别,如果加上内容约束,
比如 :{name: string} 这样名字只能是string 不能是其他类型
let obj: {} = {name:'333'}
let obj2: object = {name:111}
let obj3: {name: string} = {name: 'aaa'}
null 和undefined ,这两个类型比较特殊,他们是所有其他类型的子类型,他们可以赋值给其他类型,都不会报错,
但是会有一些隐患,如一个字符串本来是有一些方法,如substr方法,结果你的值是null,或者undefined
而他们就没有substr方法 就会报错
let num: number = null
let str: string = undefined
console.log(str.substr(0, 1));
let arr: string[] = null
为了解决这样的隐患 我们可以在tsconfig配置里面的编译选项中加上一个配置"strictNullChecks" : true,
加上这个配置后你的类型就不能赋值给null/undefined了,变成了更严格的空类型检查,从此之后 null/undefined只能赋值给自身了
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"lib":["es2016"],
"outDir": "./dist",
"strictNullChecks": true
},
联合类型
当一个变量可以是字符串也可以为空时,如果还用之前的约束方式就不可能实现,之前的约束是必须有值,
当然你可能已经接触过了,之前的数组中每一项都是不同的值时 当时我们就用了 string | number来进行约束的,
中间这个|表示的就是联合符号 例如 名字有可能不填,那么我们怎么进行约束呢
let name: string | undefined;
let age: number | undefined;
像这样约束方式就是联合类型,就可以处理当变量是多种类型的情况下的约束,
注: 在这种情况下就得判空处理,否则如果使用了一些内部函数如toString等,当值为undefined时就会报错;
如果进行了类型保护就不会出现这种问题; 如何触发类型保护呢,一般使用typeof触发简单的类型保护
void类型
通常用于约束函数的返回值,表示该函数没有任何返回值;一般不会约束变量
function print: voild(){
console.log(window)
}
never类型
通常用于约束函数的返回值,表示该函数永远不可能结束;可以约束变量,但一般不会去这样约束
function throwError(msg: string): nrver {
throw new Error(msg);
}
function alwaysDoSomething(): never {
while (true){
//...
}
}
字面量类型:
表示使用一个值进行约束
强制性把变量的值给固定了,后面赋值只能赋值你约束的字面量的值,如下:
let a: "A";
如果你想改变a的值,它是会报错的,告诉你不能赋值除“A”以外的值
a="B"
一般我们可以进行这样约束,比如对性别进行约束,
let gender: "男" | "女" | "未知";
在赋值的时候,我们只能选择“男”,“女”和“未知”这三种结果
注:在之前数组的时候提到过 为什么let arr: []= [1,2,3]不能这样写了,知道为什么了吗
在这里解释一下,字面量约束一个变量为数组,怎么进行约束,数组的符号是[],那么我们约束是不是就可以写成这样
let arr: [];
但是这个时候,你是不是就相当于把arr的值固定只能是[],这里这个符号表示的可是一个空数组;所有接下来你想给arr赋值,只能是
arr = [];
不能给数组里面加入任何东西,所有这样写let arr: []= [1,2,3]是错误的,正确的写法是
let arr1: []= []; 或者
let arr2: [1,3,4,5]= [1,3,4,5];或者
let arr3: [1,2,3];
arr3 = [1,2,3];
所以,对数组进行约束,必须得在前面加上数组的类型,否则就变成了字面量约束了,
这个时候你是不是会想到 对象,给对象约束的时候好像也是let obj: {} = {name: '333'};
按照数组的例子,这按理来说是一个空对象 不应该可以进行塞值,但是恰恰相反对象这样进行赋值没有问题,
这里想要深究可能得看源码了,我就没有去过多的研究,只是好奇的想了一下,可能是数组的一个长度问题;这就不进行深究了
元组类型(Tuple) :
一个固定长度的数组,并且数组中的每一项的类型确定
如 定义一个数组的第一项为字符串,第二项为数字
let arr: [string, number];
如果给数组赋值为空数组,结果报错不行
arr = [];
如果给数组第一项赋值为数字,也不行
arr = [1,'2'];
如果给数组长度超过两项也不行,即使是约束对了但是长度不对也不行,
arr= ["1",2,3]
只有长度,每一项都对了才行
arr= ["1",2]
any类型:
any类型可以绕过类型检查,因此,any类型的数据可以赋值给任意类型
一般不建议使用any类型进行约束,在运行中可能会存在问题,如:
let data: any = "admin";
let num: number = data;
在写的过程中不报错,但是在运行的时候会出现问题
类型别名:对已知的一些类型定义名称;
语法 type 类型名称 = 约束的东西
先看一下代码
let user:{name:string,age:number,gender:"男"|"女"|"未知"};
function getUser(g: "男"|"女"|"未知"):{name:string,age:number,gender:"男"|"女"|"未知"}[]{
//...
return [];
}
这个函数是获取的用户数据,首先参数有约束,返回值也有约束,咋一看没啥问题,确实没问题;
但是看起来不太美观,而且有重复的东西;到时候要修改还得一个一个去改麻烦
这个时候我们就可以用到我们的类型别名,就是把公共的约束封装起来,统一维护
那么我们对以上代码进行使用类型别名
type Gender = "男"|"女"|"未知"
type User = {name:string,age:number,gender:Gender};
let user: User;
function getUser(g:Gender): User[]{
//...
return []
}
这样写完 代码看起来也比较舒适,要修改类型约束时只要改Gender和User的约束就可以了
函数的约束
函数重载:在函数实现之前,对函数调用的多种情况进行声明
举个例子,下面combine函数的返回值可能是数字,也可能是字符串,
function combine(a: number | string, b: number | string): number | string {
if (typeof a === "number" && typeof b === "number") {
return a * b;
} else if (typeof a === "string" && typeof b === "string") {
return a+b;
}
throw new Error("a和b必须时相同的类型")
}
当你去调用函数传参时,不管你传递任何类型 都不会报错
let result = combine(1,'3')
如果不看函数的返回值我们是不知道必须传什么值才能得到返回值,所以最好可以在调用函数的时候就进行提示
这里我们就可以用到函数的重载 语法function 函数的名字(参数1:约束类型,参数2:约束类型,...): 约束类型(这里只写一个)
/**
* 得到a*b的结果
* @param a 数字类型
* @param b 数字类型
*/
function combine(a: number , b: number ): number;
/**
* 得到a+b的结果
* @param a 字符串类型
* @param b 字符串类型
*/
function combine(a: string, b: string): string;
function combine(a: number | string, b: number | string): number | string {
if (typeof a === "number" && typeof b === "number") {
return a * b;
} else if (typeof a === "string" && typeof b === "string") {
return a+b;
}
throw new Error("a和b必须时相同的类型")
}
像这样的写法,在调用函数的时候,如果你输入的两参数类型不同,会有报错提示,只要正确了才不会报错
let result = combine(1,3)