欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

TypeScript(数据类型、函数、类、接口、泛型)

程序员文章站 2022-07-12 15:53:25
...

TypeScript 设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何浏览器上。
JavaScript 与 TypeScript 的区别
TypeScript 是 JavaScript 的超集,支持 ECMAScript 6 标准,扩展了 JavaScript 的语法,因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。
TypeScript 可处理已有的 JavaScript 代码,并只对其中的 TypeScript 代码进行编译。

一、typeScript中的数据类型

typescript中为了使编写的代码更规范,更有利于维护,增加了类型校验,在typescript中主要给我们提供了以下数据类型
1.1 布尔类型(boolean) let flag: boolean = true;
1.2 数字类型(number) let num: number = 6;
1.3 字符串类型(string) let str: string = “str”;
1.4 数组类型(array)
var arr:number[]=[11,22,33];
var arr:Array=[11,22,33];
var arr3:any[]=[‘131214’,22,true];
1.5 元组类型(tuple)
属于数组的一种,例如数组中既可有string、又可有number
let arr:[number,string]=[123,‘this is ts’];
缺点是,必须指定的位置对用指定的类型,后面这种情况会用到任意类型 any
1.6 枚举类型(enum)
一般用于表示错误码,为了易读性强,单词可以用引号也可以不用,一般不写就是下表(从0开始,但是如果前一个有值,则从前一个的下表往后默认赋值)

enum Err {'undefined'=-1,'null'=-2,'success'=1};
var e:Err=Err.success;
console.log(e);

1.7 任意类型(any)
场景:比如获取dom节点,ts中不加类型会提示dom节点是object,但是类型没object,给了也会报错,
这种情况就需要用到any类型。
1.8 null 和 undefined 其他(never类型)数据类型的子类型
一个元素可能是 number类型 可能是null 可能是undefined
var num:number | null | undefined;
1.9 void类型
typescript中的void表示没有任何类型,一般用于定义方法的时候方法没有返回值。
无返回值

function run():void{
     console.log('run')
 }
run();

有返回值

function run():number{
    return 123;
}
run();

1.10 never类型 是其他类型 (包括 null 和 undefined)的子类型,代表从不会出现的值。
这意味着声明never的变量只能被never类型所赋值。

var a:undefined;  a=undefined;
var b:null;  b=null;

   var a:never;
    a=(()=>{

        throw new Error('错误');
    })()

但是这里也可以用any或者string代替,这里只是也可以用never

二、typeScript中的函数

2.1 函数的定义
es5定义函数的方法1函数声明法2匿名函数
ts中定义函数的方法

//函数声明法
 function run():string{
	 return 'run';
 }
//匿名函数
 var fun2=function():number{

    return 123;
 }

ts中定义方法传参

  function getInfo(name:string,age:number):string{
         return `${name} --- ${age}`;
  }
  alert(getInfo('zhangsan',20));
  
  //没有返回值的方法
  function run():void{
    console.log('run')
  }
  run();

2.2 函数的可选参数
es5里面方法的实参和行参可以不一样,但是ts中必须一样,如果不一样就需要配置可选参数

function getInfo(name:string,age?:number):string{
    if(age){
         return `${name} --- ${age}`;
    }else{
         return `${name} ---年龄保密`;
    }
}

注意:可选参数必须配置到参数的最后面

2.3 函数的默认参数
es5里面没法设置默认参数,es6和ts中都可以设置默认参数

function getInfo(name:string,age:number=20):string{
     if(age){
           return `${name} --- ${age}`;
     }else{
           return `${name} ---年龄保密`;
     }
}

2.4 函数的剩余参数
三点运算符 接受新参传过来的值

   function sum(...result:number[]):number{
      var sum=0;
      for(var i=0;i<result.length;i++){
          sum+=result[i];  
      }
      return sum;
   }
   alert(sum(1,2,3,4,5,6)) ;

   function sum(a:number,b:number,...result:number[]):number{
       var sum=a+b;
       for(var i=0;i<result.length;i++){
           sum+=result[i];  
       }
       return sum;
   }
   alert(sum(1,2,3,4,5,6)) ;

2.5 函数重载
es5中出现同名方法,下面的会替换上面的方法
ts中的重载

 function getInfo(name:string):string;
 function getInfo(age:number):string;
 function getInfo(str:any):any{
       if(typeof str==='string'){
              return '我叫:'+str;
       }else{
              return '我的年龄是'+str;
       }
 }
 alert(getInfo('张三'));   //正确
 alert(getInfo(20));   //正确
 alert(getInfo(true));    //错误写法
//可选
function getInfo(name:string):string;
function getInfo(name:string,age:number):string;
function getInfo(name:any,age?:any):any{
      if(age){
              return '我叫:'+name+'我的年龄是'+age;
      }else{
              return '我叫:'+name;
      }
 }
 alert(getInfo('zhangsan'));  //正确
 alert(getInfo(123));  //错误
 alert(getInfo('zhangsan',20));  //正确

重载的getInfo函数在调用的时候会进行正确的类型检查。

为了让编译器能够选择正确的检查类型,它与JavaScript里的处理流程相似。 它查找重载列表,尝试使用第一个重载定义。如果匹配的话就使用这个。 因此,在定义重载的时候,一定要把最精确的定义放在最前面。

注意,function getInfo(x): any并不是重载列表的一部分,
因此这里只有两个重载:一个是接收对象另一个接收数字。 以其它参数调用 getInfo会产生错误。

2.6、箭头函数 es6
this指向的问题 箭头函数里面的this指向上下文

三、typeScript中的类

首先说一下js中的继承

构造函数继承(call):可以继承构造函数中的属性和方法,但是没法继承原型链上的属性和方法

原型链实现继承:Web.prototype=new Person(),可以继承构造函数里面的属性和方法 也可以继承原型链上 面的属性和方法,但是 实例化子类的时候没法给父类传参

组合继承:需两种结合

    function Web(name,age){
        Person.call(this,name,age);   
        //可以继承构造函数里面的属性和方法、实例化子类可以给父类传参
    }
    Web.prototype=Person.prototype;//可以继承原型链上的属性和方法

当然还有其他一些继承,原型式继承、寄生式继承、寄生组合式继承,不一一介绍了。

接下类我们开始ts中的类

3.1 ts中类的定义
其实就是在es6的基础上加了类型检测

    class Person{
        name:string;   //属性  前面省略了public关键词
        constructor(name:string){  //构造函数   实例化类的时候触发的方法
            this.name=name;
        }
        getName():string{
            return this.name;
        }
        setName(name:string):void{
            this.name=name;
        }
    }
    var p=new Person('张三');
    alert(p.getName());
    p.setName('李四');
    alert(p.getName());

3.2 ts中实现继承 extends、 super
其实就是在es6的基础上加了类型检测

class Web extends Person{
    constructor(name:string){
         super(name);  /*初始化父类的构造函数*/
    }
}
var w=new Web('李四');
alert(w.getName());

ts中继承的探讨 父类的方法和子类的方法一致时,以子类方法为主

3.3 ts中类里面的修饰符
typescript里面定义属性的时候给我们提供了 三种修饰符

public :公在当前类里面、 子类 、类外面都可以访问
protected:保护类型在当前类里面、子类里面可以访问 ,在类外部没法访问
private :私有 在当前类里面可以访问,子类、类外部都没法访问

属性如果不加修饰符 默认就是 公有 (public)

3.4 ts中的静态属性 静态方法

 class Per{
    public age:number=20;
    //静态属性
    static sex="男";
    static print(){  /*静态方法  里面没法直接调用类里面的属性*/
        alert('print方法'+this.sex); //报错
        alert('print方法'+Per.sex); //需要此种方式调取静态属性
    }
 }
 Per.print();

3.5 ts中的多态、抽象类
多态:父类定义一个方法不去实现,让继承它的子类去实现 每一个子类有不同的表现,多态属于继承

抽象类:它是提供其他类继承的基类,不能直接被实例化。用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。abstract抽象方法只能放在抽象类里面,抽象类和抽象方法用来定义标准 。

abstract class Animal{
    public name:string;
    constructor(name:string){
        this.name=name;
    }
    abstract eat():any;  //抽象方法不包含具体实现并且必须在派生类中实现。
    run(){
        console.log('其他方法可以不实现')
    }
}
// var a=new Animal() /*错误的写法*/
class Dog extends Animal{
    //抽象类的子类必须实现抽象类里面的抽象方法
    constructor(name:any){
        super(name)
    }
    eat(){
        console.log(this.name+'吃粮食')
    }
}
var d=new Dog('小花花');
d.eat();

四、typeScript中的接口

接口的作用:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用。接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。 typescrip中增加了更灵活的接口类型,包括属性、函数、可索引和类等。

4.1 属性类接口
对json的约束

 function printLabel(labelInfo:{label:string}):void {
     console.log('printLabel');
 }
 printLabel('hahah'); //错误写法
 printLabel({name:'张三'});  //错误的写法
 printLabel({label:'张三'});  //正确的写法

对批量方法进行约束

 interface FullName{
       firstName:string;   //注意  ;结束
       secondName:string;
 }
 function printName(name:FullName){
       // 必须传入对象  firstName  secondName
       console.log(name.firstName+'--'+name.secondName);
 }
 printName('1213');  //错误
 var obj={   /*传入的参数必须包含 firstName  secondName*/
        age:20,
        firstName:'张',
        secondName:'三'
 ;
 printName(obj) //正确

如果不写obj对象当参数传入,而是直接写对象 printName({ firstName:‘张’,secondName:‘三’}),这时只能有firstName、secondName,否则报错

虽然上面不报错,但是当函数内部使用它时,就会报错,因为接口里面只约束了两
个字段,要使用其他的就会报错,这就是对批量方法进行约束,接口不仅传值约束,使用时也约束,所以还是老老实实按照接口来

接口 :可选属性 加?

 interface FullName{
   firstName:string;
   econdName?:string;
  }
  function getName(name:FullName){ console.log(name) }  
  getName({               
    firstName:'firstName'
  })

4.2 函数类型接口
对方法传入的参数 以及返回值进行约束 批量约束
加密的函数类型接口

interface encrypt{
    (key:string,value:string):string;
}

var md5:encrypt=function(key:string,value:string):string{
    //模拟操作
    return key+value;
}
console.log(md5('name','zhangsan'));
var sha1:encrypt=function(key:string,value:string):string{
    //模拟操作
    return key+'----'+value;
}
console.log(sha1('name','lisi'));

4.3 可索引接口
数组、对象的约束 (不常用)

 //可索引接口 对数组的约束
   interface UserArr{
         [index:number]:string
   }
   var arr:UserArr=['aaa','bbb'];/*正确*/
   console.log(arr[0]);
   var arr:UserArr=[123,'bbb'];  /*错误*/
   console.log(arr[0]);
 //可索引接口 对对象的约束
   interface UserObj{
          [index:string]:string
   }
   var arr:UserObj={name:'张三'};

4.4 类类型接口
对类的约束 和 抽象类抽象有点相似

interface Animal{
    name:string;
    eat(str:string):void;
}
class Dog implements Animal{
    name:string;
    constructor(name:string){
        this.name=name;
    }
    eat(){
        console.log(this.name+'吃粮食')
    }
}
var d=new Dog('小黑');
d.eat();
//-----------------
class Cat implements Animal{
    name:string;
    constructor(name:string){
        this.name=name;
    }
    eat(food:string){
        console.log(this.name+'吃'+food);
    }
}
var c=new Cat('小花');
c.eat('老鼠');

4.5 接口扩展
接口可以继承接口

	interface Animal{
	    eat():void;
	}
	interface Person extends Animal{
	    work():void;
	}
	class Web implements Person{
	    public name:string;
	    constructor(name:string){
	        this.name=name;
	    }
	    eat(){
	        console.log(this.name+'喜欢吃馒头')
	    }
	    work(){
	        console.log(this.name+'写代码');
	    }
	}
	var w=new Web('小李');
	w.eat();

继承类实现接口

	interface Animal{
        eat():void;
    }
    interface Person extends Animal{
        work():void;
    }
    class Programmer{
        public name:string;
        constructor(name:string){
            this.name=name;
        }
        coding(code:string){
            console.log(this.name+code)
        }
    }
    class Web extends Programmer implements Person{
        constructor(name:string){
           super(name)
        }
        eat(){
            console.log(this.name+'喜欢吃馒头')
        }
        work(){
            console.log(this.name+'写代码');
        }
    }
    var w=new Web('小李');
    // w.eat();
    w.coding('写ts代码');

五、typeScript中的泛型

泛型: 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验)。可以支持不特定的数据类型 要求:传入的参数和返回的参数一直,T表示泛型,有时候要求类型检测,但是返回任意类型,这也是泛型,只不过不常用
5.1 泛型函数

 function getData<T>(value:T):T{
    return value;
 }
 getData<number>(123);
 getData<string>('1214231');

有时候要求类型检测,但是返回任意类型,这也是泛型,只不过不常用

function getData<T>(value:T):any{
    return '2145214214';
}
getData<number>(123);  //参数必须是number
getData<string>('这是一个泛型');

5.2 泛型类
类的泛型, any没有类型校验

class MinClas<T>{
    public list:T[]=[];
    add(value:T):void{
        this.list.push(value);
    }
    min():T{        
        var minNum=this.list[0];
        for(var i=0;i<this.list.length;i++){
            if(minNum>this.list[i]){
                minNum=this.list[i];
            }
        }
        return minNum;
    }
}

var m1=new MinClas<number>();   /*实例化类 并且制定了类的T代表的类型是number*/
m1.add(11);
m1.add(3);
m1.add(2);
alert(m1.min())

var m2=new MinClas<string>();   /*实例化类 并且制定了类的T代表的类型是string*/
m2.add('c');
m2.add('a');
m2.add('v');
alert(m2.min())

5.3 泛型接口

函数类型接口

  interface ConfigFn{
      (value1:string,value2:string):string;
  }
  var setData:ConfigFn=function(value1:string,value2:string):string{
      return value1+value2;
  }
  setData('name','张三');

定义泛型接口的两种方法

//1、泛型接口
 interface ConfigFn{
     <T>(value:T):T;
 }
 var getData:ConfigFn=function<T>(value:T):T{
     return value;
 }
 getData<string>('张三');
 getData<string>(1243);  //错误
 
//---------------------

//2、泛型接口
  interface ConfigFn<T>{
      (value:T):T;
  }
  function getData<T>(value:T):T{
      return value;
  }
  
  var myGetData:ConfigFn<string>=getData;     
  myGetData('20');  /*正确*/
  // myGetData(20)  //错误
相关标签: TypeScript