1. 基本类型
1.1 普通类型
包括 boolean、number、string、undefined、null、any、unknown、void、never、object。
// 几种特殊属性说明 // any:可以表示任何类型,并且变量可以正常使用(不建议); // unknown:可以表示任何类型,但是不论用来做什么都是不合法的; // void:表示没有任何类型,值只能为 undefined 和 null;当函数没有返回值时 其返回值类型是 void。 function fn(): void {} // never:表示一个不存在的类型;never与其他类型的联合后,为其他类型; type Test = string | number | never // 相当于 type Test = string | number // object:表示非原始类型,也就是除 number,string,boolean 之外的类型;
1.2 数组类型
// 2.1 基本使用 类型[];如 number[]、string[]、any[] const arr1: number[] = [1, 2, 3] // 2.2 元组 [类型1, 类型2, ...];如 [string, number] const arr2: [string, number] = ['str', 3] // 2.3 数组泛型 Array<类型>;如 Array<number>、Array<string> const arr3: Array<number> = [1, 2, 3]
1.3 联合类型、交叉类型
1 联合类型
类型1 | 类型2;表示取值可以为多种类型中的一种;
如 number | string、(number | string)[]、Array<number | string>。
2 交叉类型
接口1 & 接口2;表示把几种类型合并起来。
// 应用场景: 比如 Student 继承 Person 上的属性 interface Person { name: string; } type Student = Person & { age: number } // 必须同时存在对应类型的 name 和 age 才符合 Student 类型 const obj: Student = { name: "lk"; age: 18 }
1.4 类型保护、类型断言
1 类型保护
通过
typeof
方法判断返回值的类型,通过返回值类型对返回值做进一步处理;最终返回 符合函数返回值类型的最终值。
function getLength(arg: number | string): number { if(typeof arg === 'string') { return arg.length } else { return arg.toString().length } }
2 类型断言
可以用来手动指定一个值的类型;使用类型断言来告诉 TS,我(开发者)比你(编译器)更清楚这个参数是什么类型,你就别给我报错了。
// 方式一: <类型>值 // 方式二: 值 as 类型 tsx中只能用这种方式 function getLength(arg: number | string): number { const str = <string>arg if (str.length) { return str.length } else { const number = arg as number return number.toString().length } }
1.5 类型推断、字面量类型
1 类型推断
TS会在没有明确的指定类型的时候推测出一个类型; 情况一: 定义变量时赋值了, 推断为对应的类型; 情况二: 定义变量时没有赋值, 推断为any类型。
2 字面量类型
有时候,我们需要定义一些常量,就需要用到字面量类型; 比如: type Sex = '男' | '女'; 这样就只能从这些定义的常量中取值,乱取值会报错。
2. 接口(Interface)
接口是对象的状态(属性)和行为(方法)的抽象(描述)。
1 使用接口来定义对象的类型
// 可选属性(age): 在可选属性名字定义的后面加一个 ? 符号 // 只读属性(id): 在属性名前用 readonly 来指定只读属性 // 拓展: 判断该用 readonly 还是 const 是要作为变量还是作为属性使用, // 作为变量使用的话用 const,若作为属性则使用 readonly。 interface IPerson { readonly id: number; name: string; age?: number; }
2 用接口表示函数
接口可以描述函数(参数的类型与返回的类型)
interface SearchFunc { (source: string, subString: string): boolean }
3 一个类可以实现多个接口(implements)
interface Foo1 { foo1(): string } interface Foo2 { foo2(): number } class Car2 implements Foo1, Foo2 { foo0() { alert('foo0') } foo1() { return 'string' } foo2() { return 123 } }
4 一个接口可以继承多个接口(extends)
interface Foo1 { foo1(): string } interface Foo2 { foo2(): number } interface NewFoo extends Foo1, Foo2 {}
3. 类型别名(type)
3.1 类型别名
类型别名会给一个类型起个新名字,有时和接口很像,但是可以作用于原始值,联合类型,元组以及其它任何你需要手写的类型。
type Name = string // 基本类型 type arrItem = number | string // 联合类型 const arr: arrItem[] = [1, '2', 3] type Person = { name: Name } type Student = Person & { grade: number } // 交叉类型 type Teacher = Person & { major: string } type StudentAndTeacherList = [Student, Teacher] // 元组类型 const list:StudentAndTeacherList = [ { name: 'lin', grade: 100 }, { name: 'liu', major: 'Chinese' } ]
3.2 type 和 interface
1 相同点
// 1 都可以定义一个对象或函数; interface Person1 { name: string } const person1: Person1 = { name: 'lin' } type Person2 = { name: string } const person2: Person2 = { name: 'lin' } // 2 都允许继承: interface PersonI { name: string } type PersonT = { name: string } // (1) interface 继承 interfacetype 使用 extends interface StudentI1 extends PersonI { grade: number } interface StudentI2 extends PersonT { grade: number } // (2) type 继承 typeinterface 使用交叉类型 & type StudentT1 = PersonI & { grade: number } type StudentT2 = PersonT & { grade: number } // const person: Student = { name: 'lin', grade: 100 }
2 不同点
// 1.interface(接口) 是 TS 设计出来用于定义对象类型的,可以对对象的形状进行描述; // 2.type 是类型别名,用于给各种类型定义别名,让 TS 写起来更简洁、清晰; // 3.type 可以声明基本类型、联合类型、交叉类型、元组,interface 不行; // 4.interface可以合并重复声明,type 不行。 // interface 重复声明不报错 interface PersonI { name: string } interface PersonI { age: number } const person: PersonI = { name: 'lin', age: 18 } // type 重复声明会报错 type PersonT = { name: string } type PersonT = { age: number } // err
4. 类
访问修饰符: 用来描述类内部的属性方法的可访问性; public: 默认值, 公开的外部也可以访问; private: 只能类内部可以访问; protected: 类内部和其子类内部可以访问; static: 类的静态属性,只能被类本身访问,而不能被实例化的对象访问。
5. 函数
5.1 为参数添加参数类型和返回值类型
```tsx function foo1(x: number, y: number): number { return x + y } ```
5.2 函数的完整类型
```tsx let foo2: (x: number, y?: number) = number = function(x: number, y: number): number { return x + y } ```
5.3 TS中的可选参数
JavaScript 里,每个参数都是可传可不传的;没传参的时候,它的值就是 undefined,但是在
TypeScript
我们需要在参数名后面使用 ? 实现可选参数的功能(比如上面的参数 y )
5.4 函数重载
函数名相同, 而形参不同的多个函数
6. 泛型
6.1 普通类型和函数泛型
// 普通类型 function foo1 (a: string, b: number): [string, number] { return [a, b] } console.log(foo1('abc', 123)) // 函数泛型 function foo2 <K> (a: K, b: number): [K, number] { return [a, b] } console.log(foo2 <string> ('abc', 123)) // 多个泛型参数 function foo3 <K, V> (a: K, b: V): [K, V] { return [a, b] } console.log(foo3 <string, number> ('abc', 123))