TS入门004接口02

接口

就是用代码描述一个对象必须有什么属性(包括方法),但是有没有其他属性就不管了

理解 函数和方法的区别

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
当一个函数是一个对象的属性的时候,我们把这个函数称为该对象的方法


------------
// 这是一个函数
function fn(){
console.log(1)
}

let obj = {
fn:function(){
console.log(2)
}
}

// obj.fn 就是一个方法

------------------------
如果这样呢?
function fn(){
console.log(1)
}
let obj = {
fn:fn
}

// fn实质就是 一个形如 addr = 2311111 的地址的内存
// 如果是普通编程角度 fn 是函数
// 如果是面向对象角度 fn 是方法

定义一个接口 人

1
2
3
4
5
6
7
interface Human{
name:string,
age:number
}

let p1:Human = {name:'hjx',age:18};
// 不加 name 报错,不加age也报错

需求添加:人有身体

1
2
3
4
5
6
7
8
9
10
11
12
interface Shape{
head:string,
body:string
}

interface Human{
name:string,
age:number,
shape:Shape
}

let p1:Human = {name:'hjx',age:18,shape:{head:'头',body:'方的'}}

需求添加:人不仅有身体,还要走路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
interface Shape{
head:string,
body:string
}

interface Human{
name:string,
age:number,
shape:Shape,
say(word: string):void;
}

let p1:Human = {
name:'hjx',
age:18,
shape:{head:'头',body:'方的'},
say(word: string){
console.log(word)
}
}

p1.say('I\'m hjx')

只读属性。需求添加:人不能改名字

1
2
3
4
5
6
7
8
9
10
interface Human{
readonly name:string,
age:number
}

let p1:Human = {name:'hjx',age:18};

p1.name = 'aaa'
// 报错
// Cannot assign to 'name' because it is a constant or a read-only property.

可选属性

  • 有些人喜欢玩游戏,有些人什么都不玩
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
interface Shape{
head:string,
body:string
}

interface Human{
readonly name :string,
age:number,
shape:Shape,
likedGame?:Array<string>;
say(word: string):void;
}

let p1:Human = {
name:'hjx',
age:18,
shape:{head:'头',body:'方的'},
likedGame:['王者荣耀','lol'],
say(word: string){
console.log(`${this.name}-${word}`);
}
}

let p2:Human = {
name:'hjx2',
age:20,
shape:{head:'头',body:'方的'},
say(word: string){
console.log(`${this.name}-${word}`);
}
}

接口应用在函数里

1
2
3
4
5
6
7
8
9
10
11
12
interface RectConfig{
height?: number,
width?: number
}

function createRect(config:RectConfig):void{

}

// 由于可选 所以可以传递一个属性
let mySquare = createRect({width:100})
let mySquare2 = createRect({height:100})
  • 如果在参数里传递多余的是不允许的
1
let mySquare3 = createRect({width:100,height:100,color:'red'})
  • 如果声明在变量里就允许
1
2
3
4
5
6
7
8
9
let config = {
height:100,
width:100,
color:'red'
}
let mySquare4 = createRect(config);


let config2 = {} //这样也可以 ,因为接口定义的参数都是可选的

都可选,同时受你控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface RectConfig{
height?: number;
width?: number;
[propName: string]: number;
}

let config = {
height:100,
width:100,
}

/*
[propName: string] 代表 key 是一个string
[propName: string]: number; 代表 key 对应的 value值必须是 number
*/

给函数定义接口

1
2
3
4
5
6
7
interface 二则运算{
(a: number,b: number): number;
}

let add:二则运算 = function(c: number, d: number): number{
return c + d;
}

- 接口里定义一个函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface 二则运算{
(a: number,b: number): number;
逆运算(a: number,b: number): number;
}

let add:二则运算=(
(): 二则运算 =>{
let x: any = function(a: number,b: number){
return a + b;
}
x.逆运算 = function(a: number,b: number): number{
return a - b;
}
return x;
}
)();

console.log(add(1,2)); // 3

接口的继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface Animal{
move(): void;
}

interface Human extends Animal{
name: string;
age: number;
}

let p: Human = {
name:'hjx',
age:18,
move(){
console.log('我在动')
}
}

p.move();
  • 多重继承
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
interface 有机物{
c:boolean;
h:boolean;
o:boolean,
}

interface Animal{
move(): void;
}


interface Human extends Animal,有机物{
name: string;
age: number;
}

let p: Human = {
c:true,
h:true,
o:true,
name:'hjx',
age:18,
move(){
console.log('我在动')
}
}

p.move();
  • 串行的继承
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
interface 有机物{
c:boolean;
h:boolean;
o:boolean,
}

interface Animal extends 有机物{
move(): void;
}


interface Human extends Animal{
name: string;
age: number;
}

let p: Human = {
c:true,
h:true,
o:true,
name:'hjx',
age:18,
move(){
console.log('我在动')
}
}

p.move();

一个接口继承了两个接口,顺序重要吗?

  • 不重要
  • 但是如果那两个接口拥有一个共同的属性就麻烦了,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
interface 有机物{
c:boolean;
h:boolean;
o:boolean;
xxx:string;
}

interface Animal{
move(): void;
xxx:number
}

// 继承的两个接口存在相同属性,没有覆盖关系,直接报错
interface Human extends Animal,有机物{
name: string;
age: number;
}

串行也报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
interface 有机物{
c:boolean;
h:boolean;
o:boolean;
xxx:string;
}

interface Animal extends 有机物{
move(): void;
xxx:number;
}

interface Human extends Animal{
name: string;
age: number;
}

除非类型一致

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
interface 有机物{
c:boolean;
h:boolean;
o:boolean;
xxx:string;
}

interface Animal extends 有机物{
move(): void;
xxx:string;
}

interface Human extends Animal{
name: string;
age: number;
}

接口的顺序写在后面可以吗?

  • 最好不要瞎写
  • ts最烦的就是 你先用,后面在声明
  • 可不可以把 interface 写后面——你有病吗?
  • 可以写在后面,但是建议写前面