学习Typescript(第二弹)

接口

对象类型接口

  • 先用interface定义一个List接口,成员有id时number类型,name是string类型
  • 再定义一个Result,成员是List数组
  • 定义一个render函数,接收参数是result

// 先用interface定义一个List接口
interface List {
    id:number,
    name:string,
}

// 再定义一个Result,成员是List数组
interface Result {
    data: List[]
}
// 定义一个render函数
function render(result:Result) {
    result.data.forEach((value) => {
        console.log(value.id, value.name)
    })
}
// 假设从后端拿到的result数据,符合我们的定义,打印出来的结果符合我们的预期
let result = {
    data:[
        {id:1,name:'a'},
        {id:2,name:'b'},
    ]
}
render(result)

  • 打印出来的结果符合我们的预期

  • 但是实际开发过程中,后端给的数据往往传过来预定之外的字段

检查原则

  • 这样ts并不会报错,因为这是鸭式辨型法:如果一只鸟看起来像鸭子,游起来像鸭子,叫起来像鸭子,那么这只鸟就可以被认为是鸭子
  • 所以只要传入的对象满足接口的必要条件,那就是允许的,也就不会报错,即使传入多余的类型字段,也可以通过类型检查。
  • 但是如果你是直接传入类型字面量的话,ts就会对额外的字段进行类型检查

如何绕过这种类型检查

  • 将对象字面量赋值给变量

  • 使用类型断言
    明确告诉编译器,这个对象的类型就是Result,这样编译器就会绕过类型检查,有两种类型断言方法,第二种在react中会产生歧义

  • 使用字符串索引签名
    用任意的字符串去索引List,可以得到任意的结果,这样List就可以支持多个属性了

对象属性

  • 可选属性,加?

如果要直接判断有没有gender属性,那ts就会报错

所以就有可选属性

  • 只读属性,加readonly,是不允许修改的

可索引类型接口

数字索引(相当于数组)[index:number]

interface StringArray {
    [index:number]: string
}

用任意的数字去索引StringArray,相当于声明了一个字符串数组

字符串索引[x:string]

如果声明了字符串索引是不可以再声明其他类型的

两种类型可以混用

这样是既可以用字符串索引Strings,也可以用数字去索引Strings

混用时数字索引的返回值类型必须是字符串索引返回值的子类型!!!这是因为JavaScript会进行类型转换,将number转换成string,这样就能保持类型的兼容性

let ss:Strings = {
    1:1,
    'aa':2,
    'bb':'cc',
}
ss[1]里面的数字number会被转换成字符串string

比如

但是你可以把上面的string类型改成any就可以兼容number了

函数类型接口

三种方式定义函数接口

混合类型接口

既可以定义一个函数,也可以像对象一样定义属性和方法

实现这个混合类型,发现会报错

给它加上属性和方法后发现还是报错

那就给它加上断言就不会有报错了

但是这样会有一个问题,给全局暴露了一个变量类,它是一个单例,如果想创建多个lib,那就要用一个函数封装一下,这样可以创建多个实例

函数

函数定义

  • 定义方式:变量定义、function、类型别名、接口定义;这些都是定义函数类型,无函数体
  • 类型要求:参数类型必须声明;返回值类型一般无需声明。

函数参数

  • 参数个数:实参和形参必须一一对应

  • 可选参数:必选参数不能放在可选参数后

  • 默认参数:在必选参数前,默认参数不可省略;在必选参数后,默认参数可以省略

  • 剩余参数

函数重载

  • 静态类型语言:函数的名称相同,参数的个数或类型不同
  • Typescript:预先定义一组名称相同,类型不同的函数声明,并在一个类型最宽松的版本中实现;使用相同名称和不同参数数量或类型创建多个方法的一种能力
  • 函数重载真正执行的是同名函数最后定义的函数体 在最后一个函数体定义之前全都属于函数类型定义 不能写具体的函数实现方法 只能定义类型

基本实现

  • 类中定义的属性都是实例属性,类中定义的方法都是原型方法
class Car {
    constructor(name:string) {
        this.name = name;
    }
    name:string
    getColor() {}
}

console.log(Car.prototype); // 打印出来是不包含内部属性name的

打印出来是不包含内部属性name的


属性在实例上

let car = new Car('BMW');
console.log(car);

  • 实例属性必须有初始值, 或在构造函数中被赋值,或为可选成员
class Car {
    constructor(name:string) {
        // this.name = name; // 在构造函数中被赋值
    }
    name:string = 'BMW' // 要给一个初始值
    getColor() {}
}

继承

  • 子类的构造函数中必须包含super调用
class BMW extends Car {
    constructor(name:string, color:string){
        super(name); // 子类的构造函数中必须包含super调用
        this.color = color // 子类自己声明的变量要在super之后
    }
    color:string
}

成员修饰符

  • public: 对所有人可见,所有成员默认为 public

  • private:

    • 只能在被定义的类中访问,不能通过实例或子类访问;

  • private constructor:不能被实例化,不能被继承;

  • protected:

    • 只能在被定义的类和子类中访问,不能通过实例访问;

    • protected constructor:只能被实例化,不能被继承;

  • readonly: 必须有初始值,或在构造函数中被赋值

  • static: 只能由类名调用,不能通过实例访问,可继承

构造函数参数中的修饰符

  • 将参数变为实例属性

抽象类

  • 不能被实例化,只能被继承

    • 抽象方法包含具体实现 子类直接复用

    • 抽象方法不包含具体实现 子类必须实现

  • 多态

    • 多个子类对父抽象类的方法有不同实现,实现运行时绑定

abstract class Robot {
    move(){
        console.log('move');
    }
    abstract speed():void
}
class Car extends Robot {
    constructor(name:string) {
        super()
        this.name = name;
    }
    name:string
    getColor(){}
    speed(){
        console.log('car speed');
    }
}
let car = new Car('BMW');
car.move()
class Electrical extends Robot {
    speed(){
        console.log('Electrical speed');
    }
}

let elec = new Electrical();

let robots:Robot[] = [car,elec]
robots.forEach(i => {
    i.speed()
})

this 类型

本质上是原型链的调用

  • 实现实例方法的链式调用

  • 在继承时,具有多态性,保持父子类之间接口调用的连贯性

类与接口的关系

  • 类实现接口的时候,必须实现接口中所有的属性

  • 可以实现自己的属性

  • 接口只能约束类的公有public成员

  • 接口也不能约束类的构造函数

  • 接口继承

    • 接口可以继承接口,实现接口的复用

    • 接口继承类,不能继承带有私有属性和受保护成员的类

总结

本篇罗列了接口、函数、类,写的非常详细了,仔细琢磨

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值