# 接口类型

接口语法规范

定义接口的语法规范: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

# 索引类型


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

# 函数类型


// 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

# 接口的继承


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

# 交叉类型


// 一种组合类型的方式: 联合类型
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

# 接口的实现 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

# 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

# 字面量赋值



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

# 枚举类型的使用


// 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

# 枚举类型的值


// 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
Last Updated: 2/23/2023, 9:05:22 AM