美文网首页
02|typescript常用实例

02|typescript常用实例

作者: 雪燃归来 | 来源:发表于2020-05-17 12:50 被阅读0次

    一、定义索引数组

    interface StringArray{
        [index: number]: string
    }
    let chars: StringArray = ['A', 'B']
    
    interface Names{
        [x:string]: string,
        [y:number]: string
    }
    

    二、定义函数

    //example one
    function add(x:number, y:number){
      return x + y
    }
    //example two
     let add:(x:number, y:number) => number
    
    //example three
    interface add{
        (x:number, y:number): number
    }
    //example four
    type Add = (x:number, y:number) => number
    
    //实现具体的函数
    let add:Add = (a,b) => a + b
    
    // 定义混合类型
    interface Lib{
        (): void;                        //表明Lib类是一个不带返回值得函数
        version: string;            //表明Lib类有version这个属性
        dosomething():void    // 表明Lib类有dosomething这个方法
    }
    
    function getLib(){
        let lib:Lib = (() => {}) as Lib;
        lib.version = '1.0.1';
        lib.dosomething = () => {}
        return lib;
    }
    
    let lib1 = getLib()
    lib1()
    lib1.dosomething()
    

    函数参数可选

    function add5(x:number,y?:number){
        return y ? x + y : x;
    }
    

    函数参数默认值

    function add6(x:number, y=0, z:number,q=1){
        return x + y + z + q
    }
    console.log(add6(1, undefined, 3))
    

    函数参数的剩余变量

    function add7(x:number, ...rest:number[]){
        return x + rest.reduce((pre, cur) => pre + cur)
    }
    console.log(add7(1,2,3,4,5))
    

    函数的重载

    // 函数的重载
    function add8(...rest:number[]):number;
    function add8(...rest:string[]):string;
    function add8(...rest:any[]):any{
        let first = rest[0];
        if(typeof first === 'string'){
            return rest.join('')
        }
        if(typeof first === 'number'){
            return rest.reduce((pre, cur) => pre + cur)
        }
    }
    
    console.log(add8(1,2,3))
    console.log(add8('a','b','c'))
    

    三、ts中的类

    类的定义

    class Dog {
        constructor(name:string){
            this.name = name
        }
        name: string
        run(){}
    }
    console.log(Dog.prototype)              //{run: ƒ, constructor: ƒ}
    let dog =new Dog('wangwang')
    console.log(dog)                              // Dog {name: "wangwang"}
    

    \color{red}{注意:name属性存在实例上,而不是类上面。}
    类的继承

    class Husky extends Dog{
        constructor(name:string, color:string){
            super(name);
            this.color = color;
        }
        color:string
    }
    

    类的修饰符
    1、public 默认设置
    2、protected: 只能在类自身和子类中使用(也就是只能继承)
    3、private:只能在类本身使用
    4、readonly: 只读属性
    5、static:静态修饰符(只能通过类名来调用,也可以被继承)
    6、构造函数的参数用修饰符修饰后,会转化成示例属性

    class Husky extends Dog{
        constructor(name:string, public color:string){
            super(name);
            this.color = color
        }
        // color:string
    }
    
    let husky = new Husky('wangwang','white')
    console.log(husky)
    

    抽象类
    抽象类只能被继承,不能被实例化
    抽象方法的好处是,明确知道子类中有具体的实现,所以就不在父类中实现了
    抽象类的好处就是能抽出事务共性,有利于代码的复用和扩展

    abstract class Animal{
        eat(){
            console.log('eat')
        }
       abstract sleep():void
    }
    //let animal = new Animal()  //Cannot create an instance of an abstract class.ts(2511)
    class Dog extends Animal{
        constructor(){
            super();
        }
        sleep(){
            console.log('sleep...')
        }
    }
    
    let dog = new Dog()
    dog.eat()
    

    抽象类实现多态

    abstract class Animal{
        eat(){
            console.log('eat')
        }
        abstract sleep():void
    }
    //let animal = new Animal()  //Cannot create an instance of an abstract class.ts(2511)
    class Dog extends Animal{
        constructor(){
            super();
        }
        sleep(){
            console.log('Dog sleep...')
        }
    }
    
    class Cat extends Animal{
        sleep(){
            console.log('Cat sleep...')
        }
    }
    
    let dog = new Dog()
    let cat = new Cat()
    let animals: Animal[] = [dog, cat]
    animals.forEach(i => {
        i.sleep()
    })
    
    image.png

    通过返回this实现链式调用

    class WorkFlow{
        step1(){
            return this;
        }
        step2(){
            return this;
        }
    }
    
    new WorkFlow().step1().step2()
    

    继承的时候 this也可以表现出多态,既可以是父类型,也可以使子类型

    class WorkFlow{
        step1(){
            return this;
        }
        step2(){
            return this;
        }
    }
    
    class MyFlow extends WorkFlow{
        next(){
            return this;
        }
    }
    
    new MyFlow().next().step1().next().step2()
    

    四、ts中接口与类的关系

    一个接口可以约束一个类成员有哪些属性以及他们的类型
    类实现接口时,必须要实现接口所有的属性和方法
    接口只能约束类的公用成员
    接口不能约束类的构造函数

    interface Human{
        name: string;
        eat():void;
    }
    
    class Asian implements Human{
        constructor(public name: string){
            this.name = name
        }
        eat(){}
        sleep(){}
    }
    

    接口也可以继承接口
    一个接口可以继承多个接口
    可以抽离处可重用的接口,也可以将多个接口合并成一个接口

    interface Human{
        name: string;
        eat():void;
    }
    
    class Asian implements Human{
        constructor(public name: string){
            this.name = name
        }
        eat(){}
        sleep(){}
    }
    interface Man extends Human{
        run(): void
    } 
    interface Child{
        cry():void
    }
    
    interface Boy extends Man,Child{}
    let boy:Boy = {
        name: '',
        run(){},
        eat(){},
        cry(){}
    }
    

    接口可以继承类,接口将类的成员抽象了出来,只有类的成员结构,没有具体的实现

    class Auto {
        state = 1
    }
    interface AutoInterface extends Auto{
    
    }
    
    class C implements AutoInterface{
        state = 1
    }
    
    class Bus extends Auto implements AutoInterface{
    
    }
    let c = new C();
    console.log(c.state)
    
    image.png

    五、ts中的泛型

    可以自定义化函数参数的类型
    使用泛型定义一个函数

    function log<T>(value: T): T{
        console.log(value)
        return value
    }
    
    log<string[]>(['a', 'b'])
    log(['a','b'])
    

    使用泛型定义一个函数类

    function log<T>(value: T): T{
        console.log(value)
        return value
    }
    
    log<string[]>(['a', 'b'])
    log(['a','b'])
    
    type Log = <T>(value: T) => T
    let myLog:Log = log
    

    使用泛型定义接口

    interface Log{
        <T>(value: T): T
    }
    
    function log<T>(value: T):T{
        console.log(value)
        return value
    }
    interface Log<T = string>{
        (value: T): T
    }
    // let myLog: Log<number> = log
    let myLog: Log = log;
    

    泛型不能约束类的静态成员

    class Log<T>{
        // Static members cannot reference class type parameters.ts(2302)
        static run(value: T){ 
            console.log(value)
            return value
        }
    }
    
    interface Length{
        length: number
    }
    
    function log<T extends Length>(value: T): T{
        console.log(value, value.length)
        return value
    }
    log([1])
    log('123')
    log({length: 1})
    

    泛型的好处
    1、函数和类可以轻松地支持多种类型,增强程序的扩展性
    2、不必写多条函数重载,很长的联合类型声明,增强代码可读性
    3、灵活控制类间的约束

    六、类型兼容性

    (一)、接口的兼容性

    X 兼容 Y: X(目标类型) = Y(源类型)

    interface X{
        a: any;
        b: any;
    }
    
    interface Y {
        a: any;
        b: any;
        c: any;
    }
    let x: X = {a: 1, b: 1}
    let y: Y = {a:1, b:2, c:3}
    x = y
    // y = x  // Y 不兼容 X
    

    (二)、函数的兼容性

    1)参数的个数

    参数少的 兼容参数多的

    // 函数的兼容性
    type Handler = (a:number) => void;
    function hof(handler: Handler){
        return handler;
    }
    
    // 1)参数的个数
    let handler1 = (a:number) => {}
    hof(handler1)
    let handler2 = (a:number,b:number) => {}
    hof(handler2)  ////Argument of type '(a: number, b: number) => void' is not assignable to parameter of type 'Handler'.ts(2345)
    
    /**固定参数可以兼容可选参数和剩余参数**/
    /**可选参数是不兼容固定参数和剩余参数的**/
    /**剩余参数是可以兼容可选参数和固定参数的**/
    let a = (p1:number, p2:number) => {} 
    let b = (p1?:number, p2?:number) => {}
    let c = (...args:number[]) => {}
    
    // ok
    a = b;
    a = c;
    // unassignable
    b = a;
    b = c;
    // ok
    c = a
    c = b
    
    2)参数的类型

    类型多的兼容类型少的

    interface Point3D{
        x: number
        y: number
        z: number
    }
    
    interface Point2D{
        x: number
        y: number
    }
    
    let p3d = (point: Point3D) => {}
    let p2d = (point: Point2D) => {}
    
    // ok
    p3d = p2d
    // assignable
    p2d = p3d
    
    3)参数的返回值类型

    返回值多的兼容返回值多少的(鸭式变形法)

    let p3d = (point: Point3D) => {}
    let p2d = (point: Point2D) => {}
    
    let f = () => ({name: 'Alice'})
    let g = () => ({name: 'Alice', location:'beijing'})
    // ok
    f = g
    // unassignable
    g = f
    
    function overload(a:number, b:number): number;
    function overload(a:string, b:string): string;
    function overload(a: any, b:any): any {}
    

    (三)、枚举的兼容性

    枚举类型和数字是可以相互兼容的

    enum Fruit { Apple, Banana }
    enum Color { Green, Red }
    
    let fruit: Fruit.Apple = 3
    let no:number = Fruit.Apple
    

    枚举类型是不相互兼容的

    let color: Color = Fruit.Apple  // Type 'Fruit.Apple' is not assignable to type 'Color'.ts(2322)
    

    (四)、类的兼容性

    类之间只要有相同的实例属性和方法,就可以兼容,静态/构造属性、方法不参与兼容性比较

    class A {
        constructor(p:number, q:number){}
        id: number = 1
    }
    class B {
        static s = 1;
        constructor(p: number){}
        id: number = 1
    }
    
    let aa = new A(1,2)
    let bb = new B(2)
    // ok
    aa = bb
    // ok
    bb = aa
    

    当类中存在private私有变量时,只有子类和父类兼容

    class A {
        constructor(p:number, q:number){}
        id: number = 1
        private name = 'antiai'
    }
    
    class C extends A{}
    
    let aa = new A(1,2)
    let cc = new C(1,2)
    aa = cc
    cc = aa
    

    (四)、泛型的兼容性

    只有类型参数T被泛型接口使用的时候,才会影响泛型的兼容性

    // 兼容
    interface Empty<T>{
    
    }
    
    let obj1: Empty<number> = {}
    let obj2: Empty<string> = {}
    
    obj1 = obj2
    obj2 = obj1
    
    // 不兼容
    interface Empty<T>{
        value: T
    }
    
    let obj1: Empty<number> = {}
    let obj2: Empty<string> = {}
    
    obj1 = obj2
    obj2 = obj1
    

    (五)、泛型函数的兼容性

    如果两个泛型参数的定义相同,但是没有指定类型参数,他们之间也是相互兼容的

    let log1 = <T>(x: T) => {
        console.log(x)
        return x
    }
    let log2 = <U>(y: U) => {
        console.log(y)
        return y
    }
    
    log1 = log2
    log2 = log1
    

    结构之间兼容:成员少的兼容成员多的
    函数之间兼容:参数多的兼容参数少的

    相关文章

      网友评论

          本文标题:02|typescript常用实例

          本文链接:https://www.haomeiwen.com/subject/bnrrohtx.html