一、基础类型 1.布尔类型
1 2 3 let bool: boolean; bool = false; bool = 123; // Error:不能将类型“number”分配给类型“boolean”。
2.数值类型
3.字符串类型
1 2 3 let str: string; str = 'bac'; str = `数值是${num}`;
4.数组类型
1 2 3 4 5 6 7 8 let arr1: number[]; arr1 = [1, 2, 3]; let arr2: Array<number>; arr2 = [1, 2, 3]; let arr3: (string | number)[]; arr3 = [1, '2', 3];
5.元组类型
1 2 3 4 let tuple: [string, number, boolean]; tuple = ['a', 1, false]; // 必须按照上面的顺序和类型 tuple = ['a', false, false]; // Error:不能将类型“boolean”分配给类型“number”。 tuple = ['a', 1, false, 12]; // Error:不能将类型“[string, number, false, number]”分配给类型“[string, number, boolean]”。
6.枚举类型
1 2 3 4 5 6 7 enum Roles { SUPER_ADMIN, // 0 ADMIN, // 1 USER // 2 } console.log(Roles.SUPER_ADMIN); // 0 console.log(Roles[Roles.SUPER_ADMIN]); // SUPER_ADMIN
7.any类型
1 2 3 4 5 let value: any; value = 'abc' value =2 value = [1,2,3] let arr: any[] = [1,'a']
8.void类型
1 2 3 4 5 6 const consoleText = (text: string): void => { // 不返回内容 console.log(text); }; let v: void; v = undefined; v = null; // tsconfig的strict需要关掉
9.null和undefined
null 和 undefined 是其他类型的子类型
10.never类型
表示永远不存在的类型,抛错or死循环,返回值就是 never 类型。
1 2 3 4 5 6 7 8 9 10 const errorFunc = (message: string): never => { throw new Error(message); }; const infiniteFunc = (): never => { while(true) {} }; // let neverVariable: never let neverVariable = (() => { while(true) {} })();
11.对象类型
1 2 3 4 5 function getObject(obj: object): void { console.log(obj); } getObject({ name: 'dylan' }); getObject(123); // Error:类型“number”的参数不能赋给类型“object”的参数。
12.类型断言
值 as 类型
或 <类型>值
二、Symbol Symbol值是独一无二的
1 2 3 const s1 = Symbol(); // Symbol() const s2 = Symbol(); // Symbol() s1 === s2; // false
目前来说工作上遇到的少
三、接口 我们可以使用接口来进行限制,使数据更加清晰直观
1 2 3 4 5 6 7 8 9 10 11 interface NameInfo { firstName?: string;//?代表可选参数,没?不传这个值会报错 readonly lastName: string; //只读属性,不能更改NameInfo.lastName的值 } const getFullName = ({ firstName, lastName }: NameInfo): string => { return `${firstName} ${lastName}`; }; getFullName({ firstName: 'haha', lastName: 'Lv' });
多传入参数时使用类型断言或者索引签名
1 2 3 4 5 6 7 8 9 interface Vegetable { color?: string; type: string; } const getVegetables = ({ color, type }: Vegetable) => { return `A ${color ? (color + ' ') : ''}${type}`; }; getVegetables({ type: 'tomato', size: 2 }); // Error:类型“{ type: string; size: number; }”的参数不能赋给类型“Vegetable”的参数。
1 2 3 4 5 6 7 8 9 10 //类型断言 getVegetables({ type: 'tomato', size: 2 } as Vegetable); //索引签名 interface Vegetable { color?: string; type: string; [prop: string]: any; // 索引签名 } getVegetables({ type: 'tomato', size: 2 });
定义函数结构
1 2 3 4 5 // 等同于类型别名:type AddFunc = (num1: number, num2: number) => number; interface AddFunc { (num1: number, num2: number): number } const add: AddFunc = (n1, n2) => n1 + n2;
索引类型
1 2 3 interface RoleDic { [id: number]: string;//id这个索引只能为数值类型 }
接口的继承
1 2 3 4 5 6 7 8 9 10 interface Vegetables { color: string; } interface Tomato extends Vegetables { radius: number; } const tomato: Tomato = { radius: 1, color: 'red' };
四、泛型 T 为什么要用泛型? 可以在函数调用时自由化传入的值和返回的值
使用范型约束函数类型:与之前不同的地方在于多了 T 这个泛型参数,可以理解为这个函数:传入了 T(某个类型)作为 value 的类型,返回由 T组成的数组
1 2 3 4 5 6 7 //<T> 表示声明一个表示类型的变量,Value: T 表示声明参数是 T 类型的,后面的 : T 表示返回值也是 T 类型的 const getArray = <T>(value: T, times: number = 5): T[] => { return new Array(times).fill(value) } //如果使用any[]参数也可以任意传,但是也丢失了类型检测的功能 //第一个T为string,那么value: T也该为string getArray<string>('abc').map(item => item.length); // [3, 3, 3, 3, 3]
使用两个范型变量
1 2 3 4 5 6 // 参数1是T类型,参数2是U类型,返回类型是元组类型 T,U组成的数组 const getArray = <T, U>(param1: T, param2: U, times: number): [T, U][] => { return new Array(times).fill([param1, param2]); }; // 也可以明确泛型调用,不明确的话,TS会自动推导泛型类型:getArray<number, string>(1, 'a', 3); getArray(1, 'a', 3); // [[1, 'a'], [1, 'a'], [1, 'a']]
五、交叉类型 交叉类型就是取多个类型的并集,使用 & 符号定义。
1 2 3 4 5 6 const mergeFunc = <T, U>(arg1: T, arr2: U): T & U => { let res = {} as T & U; // 使用类型断言来告诉TS这里是(T和U)的交叉类型 res = Object.assign(arg1, arr2); return res; }; mergeFunc({ a: 'a' }, { b: 'b' });