# 接口类型
接口语法规范
定义接口的语法规范:interface 接口名 { 接口名:统一开头用大写字母I开头 }
如:interface IPerson
# 声明对象类型
// 通过类型(type)别名来声明对象类型
// type Person = {name: string, age: number}
// 另外一种声明对象类型的方式:接口(interface)
// interface: 在其中可以定义可选类型 也可以定义只读类型
// readonly 只读属性
interface IPerson {
readonly name: string,
age: number,
friend?: {
name: string,
age: number
}
}
const info: IPerson = {
name: 'zhangsan',
age: 20
}
console.log(info.name);
// info.name = 'lisi'; // 无法分配到 "name" ,因为它是只读属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 索引类型
interface IIndexType {
// 索引类型
// [index: number] 表示索引类型为number
// string 表示索引类型的值为string
[index: number]: string
}
const obj: IIndexType = {
0: 'a',
1: 'b',
2: 'c',
// "abc": 'd' // 无法将类型“"d"”分配给类型“string”
}
interface IIndexType2 {
[index: string]: number
}
const obj2: IIndexType2 = {
a: 1,
b: 2,
"abc": 3
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 函数类型
// type 别名定义: type CalaFn = (a: number, b: number) => number
// interface 定义: interface CalaFn { (a: number, b: number): number }
// 可调用的接口
interface CalaFn {
// 左边是参数列表,右边是返回值类型
(a: number, b: number): number
}
function calc(num1:number, num2:number, CalaFn: CalaFn) {
return CalaFn(num1,num2);
}
function add(a: number, b: number) {
return a + b;
}
console.log(calc(10,20,add));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 接口的继承
interface ISwim {
// 接口中的方法
// 1. 方法名 2. 参数列表 3. 返回值类型
swimming:() => void
}
interface IFly {
flyimg:() => void
}
// 接口的继承
// IAction 会继承 ISwim 和 IFly 两个接口中的方法
interface IAction extends ISwim, IFly {
// 接口中的方法
}
// const action: IAction = {} // 类型“{}”缺少类型“IAction”中的以下属性: swimming, flyimg
const action: IAction = {
swimming() {},
flyimg() {}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 交叉类型
// 一种组合类型的方式: 联合类型
type lzpType = string | number;
// 另外一种组合类型的方式: 交叉类型
type lzpType2 = string & number;
// 交叉类型的使用场景
interface ISwim {
// 接口中的方法
// 1. 方法名 2. 参数列表 3. 返回值类型
swimming:() => void
}
interface IFly {
flyimg:() => void
}
type IAction = ISwim & IFly; // 交叉类型 必须同时满足两个接口中的方法
type IAction1 = ISwim | IFly; // 联合类型 只需要满足其中一个接口中的方法
const action: IAction = {
swimming() {},
flyimg() {}
}
const action1: IAction1 = {
swimming() {},
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 接口的实现 implements
// 接口一
interface ISwim{
// 接口中的方法
swimming:() => void
}
// 接口二
interface IFly{
// 接口中的方法
flyimg:() => void
}
// 类 接口的实现
class Animal{}
// 类 的继承和接口的实现
class Person extends Animal implements ISwim, IFly{
// implements 实现接口
// 继承:只能实现单继承
// 实现:实现接口,一个类可以实现多个接口
// Person继承了ISwim 和 IFly接口 也就是说Person类中必须实现接口中的方法
// 实现接口中的方法
swimming() {
console.log('Person---------swimming');
}
flyimg() {
console.log('Person--------flyimg');
}
}
class Fish implements ISwim{
swimming() {
console.log('Fish---------swimming');
}
}
// 编写一些公共的api:面向接口编程
function useSwim(swim: ISwim) {
swim.swimming();
}
// 1.所有实现了接口的类对应的对象,都可以传入
useSwim(new Person());
useSwim(new Fish());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# interface和type的区别
// 如果是定义非对象类型,通常推荐使用type,比如一些联合类型和一些函数类型;
/**
* 如果是定义对象类型,那么他们是有区别的:
* interface可以重复的对某个接口来定义属性和方法
* 而type定义的是别名,别名是不能重复的
*/
// 接口 IAnimal 定义了两次 name 和 age 属性 但是没有报错 说明接口可以重复定义
// 属性 和 方法 会合并
interface IAnimal {
name: string;
}
interface IAnimal {
age: number;
}
const info:IAnimal = {
name: 'lzp',
age: 18
}
// type 别名不能重复定义
// type Window = {
// title: string;
// }
// error 标识符“Window”重复
// type Window = {
// age: string;
// }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 字面量赋值
interface IPerson {
name: string,
age: number,
height: number
}
// 使用IPerson 接口来约束对象
// const info: IPerson = {
// name: 'zhangsan',
// age: 20,
// height: 180,
// address: 'beijing' // 无法分配到 "address" ,因为它不在类型 "IPerson" 中
// }
// 通过字面量来推断类型
// const info = {
// name: 'zhangsan',
// age: 20,
// height: 180,
// address: 'beijing'
// }
// const info2: IPerson = info
// console.log(info);
// console.log(info2);
function printInfo(info: IPerson) {
console.log(info);
}
// 报错
// printInfo({
// name: 'zhangsan',
// age: 20,
// height: 180,
// address: 'beijing' // 无法分配到 "address" ,因为它不在类型 "IPerson" 中
// })
const info = {
name: 'zhangsan',
age: 20,
height: 180,
address: 'beijing'
}
printInfo(info)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 枚举类型的使用
// type Direction = "left" | "right" | "top" | "bottom";
// 枚举类型:
// 一组有名字的常量集合 (枚举成员)
// (枚举成员的值是从0开始自增的数字,也可以手动赋值)
// (枚举成员的值可以是数字或字符串)
// 案例: 定义一个方向的枚举类型
enum Direction {
LEFT, // 0 LEFT这种写法等等于 LEFT = 0
RIGHT, // 1
TOP, // 2
BOTTOM // 3
}
// 使用枚举类型 (枚举类型的值是从0开始自增的数字)
// direction: Direction.LEFT => 0
function turnDirection(direction: Direction) {
switch (direction) {
case Direction.LEFT:
console.log("向左");
break;
case Direction.RIGHT:
console.log("向右");
break;
case Direction.TOP:
console.log("向上");
break;
case Direction.BOTTOM:
console.log("向下");
break;
default:
const foo: never = direction;
break;
}
}
turnDirection(Direction.LEFT);
export {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 枚举类型的值
// type Direction = "left" | "right" | "top" | "bottom";
// 枚举类型:
// 一组有名字的常量集合 (枚举成员)
// (枚举成员的值是从0开始自增的数字,也可以手动赋值)
// (枚举成员的值可以是数字或字符串)
// 案例: 定义一个方向的枚举类型
enum Direction {
LEFT, // 0 LEFT这种写法默认等等于 LEFT = 0
RIGHT, // 1
TOP, // 2
BOTTOM // 3
}
// 也可以手动赋值
// 赋值类型可以是数字或字符串
// 可以手动赋值的枚举成员的值是数字,如果只赋值了第一个 那么后面的枚举成员的值是前面枚举成员的值加1
enum Direction2 {
LEFT = 100,
RIGHT = 120,
TOP = 140,
BOTTOM = 160
}
// 使用枚举类型 (枚举类型的值是从0开始自增的数字)
// direction: Direction.LEFT => 0
function turnDirection(direction: Direction) {
console.log(direction); // 这里打印出来的是数字 0
switch (direction) {
case Direction.LEFT:
console.log("向左");
break;
case Direction.RIGHT:
console.log("向右");
break;
case Direction.TOP:
console.log("向上");
break;
case Direction.BOTTOM:
console.log("向下");
break;
default:
const foo: never = direction;
break;
}
}
turnDirection(Direction.LEFT);
export {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
← TypeScript中的类 泛型的使用 →