美文网首页
TypeScript学习笔记

TypeScript学习笔记

作者: 男人宫 | 来源:发表于2022-12-20 15:00 被阅读0次
    //typeScript数据类型
    //ts有类型推导,你可以不必写后面的类型,ts会在第一次赋值时自动推导出数值的类型
    //布尔类型(blooean)
    let flag: boolean = true;
    // 简写成let flag = true //会自动推导出事blooean类型
    flag = false;
    //数字类型(number).这里整数和浮点数统称为number类型
    let a: number = 123;
    a = 456;
    a = 1.223;
    console.log(a);
    //字符串类型(string)
    let str: string = "你好啊";
    str = "哈哈哈";
    //数组类型(array)
    //es5的数组可以随便定义,不能我们一般不这么使用 var arr = [1, "你好", true]
    //es6
    //第一种定义方式
    let arr: number[] = [1, 2, 3];
    //第二种(运用泛型)
    let arr1: Array<number> = [4, 5, 6];
    
    //元组类型(tuple) 相当于属于数组的一种,只是每一项可以定义类型
    let yuanzu: [number, string, boolean] = [1, "呵呵呵", false];
    
    //枚举类型(enum)
    
    enum Status {
      suncces_t = 200,
      err_t = 404,
    }
    var q_status: Status = Status.err_t;
    console.log(q_status);
    
    //如果枚举变量不设定初始值,默认的是从0开始的数字索引值
    enum Color {
      red,
      blue,
      orange,
    }
    console.log(Color.red); //输出结果是0
    console.log(Color.blue); //输出结果是1
    console.log(Color.orange); //输出结果是2
    
    enum Color1 {
      red,
      blue = 10,
      orange,
    }
    console.log(Color1.red); //输出结果是0
    console.log(Color1.blue); //输出结果是10
    console.log(Color1.orange); //输出结果是11
    
    //任意类型(any)
    
    let num: number = 12;
    // num = "你好"  如果这样赋值的话会报错,因为typescript是严格数据类型,类型不一样会报错
    let num1: any = false;
    num1 = "jjj"; //随便赋值不会报错,任意类型的值都可以
    num1 = null;
    console.log(num1);
    //-----任意类型的用法
    //如下常在js写的代码 在js中不会报错  但在ts中会报错  var box = document.getElementById("box") box.style.color="red"
    
    //在ts中应该这么写
    // var box: any = document.getElementById("box");
    // box.style.color = "red";
    
    //null和undfiend (是其他(never类型)数据类型的子类型)
    // var b:number  console.log(b) //输出undefined 报错
    //正确写法
    var b: undefined;
    console.log(b);
    //联合类型
    var c: number | undefined; //管道符可以给定义多个类型 满足其中一个就行
    console.log(c);
    c = 100;
    console.log(c);
    
    //定义为null,值只能为null
    var d: null;
    d = null;
    
    var e: string | null | undefined;
    e = null;
    e = undefined;
    e = "饿了么";
    console.log(e);
    
    //void类型:表示没有任何类型,一般用于定义方法时的没有返回值
    //es5定义方法
    function run() {
      console.log("跑步");
    }
    
    //在ts中定义没有返回值的方法
    //定义方式 function(形参1:参数类型,形参2:参数类型):返回值类型 {}
    
    //void表示方法没有返回任何值(注意没有返回值和返回null和undifend不同,null和undefined也是数据类型)
    function swim(): void {
      console.log("我会游泳");
    }
    function goschool(name: string, age: number): string {
      return `我是${name},今年${age}岁`;
    }
    let dec = goschool("小敏", 5);
    console.log(dec);
    
    //never类型:完全无返回值的类型,只有一种情况会如此:代码阻断
    //这意味着当执行throw new Error, return process.exit(1),while(true){}这些代码时满足条件
    //如果函数的返回值类型是 never 意味的此函数必须不能被顺利完整执行,而发生中断行为
    
    var n: never;
    //所有类型的子类型
    function fun(s: string): number {
      if (s == "a") return 1;
      if (s == "b") return 2;
      throw new Error();
    }
    // 等同于 fun(s: string): number | never
    
    // 函数定义
    //    function 函数名(形参1:参数类型,形参2:参数类型):返回值类型 {}
    //匿名函数
    var func = function () {};
    //方法的可选参数:在es5里面的方法的实参和形参可以不一样,但在ts中必须一样,如果不一样就需要配置可选参数
    // function 方法名(必传形参: 形参类型,可选形参?:形参类型):返回值{}
    //注意可选参数必须配置到参数的最后面
    function eat(name: string, age?: number): string {
      if (age) {
        return `我是${name},今年${age}岁,我爱吃饭`;
      } else {
        return `我是${name},我爱吃饭`;
      }
    }
    console.log(eat("小明"));
    console.log(eat("小明", 20));
    //函数默认参数
    //在es5中没法设置默认参数,在es6和ts中都可以设置默认参数
    function eat1(name: string, age: number = 20): string {
      return `我是${name},今年${age}岁,我爱吃饭`;
    }
    //剩余参数:
    function sum(a: number, b: number, ...reslult: number[]): number {
      let sum = a + b;
      for (let i = 0; i < reslult.length; i++) {
        sum += reslult[i];
      }
      return sum;
    }
    console.log(sum(1, 2, 3, 4, 5)); //会把1赋值给a,2赋值给b,剩余的放到剩余参数的数组中
    
    //函数重载
    //函数名相同,参数类型不同
    /*
    此功能真鸡肋,ts重载的作用,感觉只是多了一个参数校验的功能。
    也就是说在进行函数调用的时候,会对参数进行检查,只有传入的参数类型,顺序,个数与定义的重载函数的参数相同,才能调用成功,否则报错。
    返回值类型不会进行校验(函数重载与返回值类型无关)
    */
    function getInfo(num1: string,num2: string): string;
    function getInfo(num1: number,num2:number): number;
    function getInfo(a: any, b:any): any {
     return  a+ b
    /如果比较复杂时可以先判断类型再进行操作
     //if(typeof a === 'string' && typeof b === 'string'){...return...}else{...return..}
    }
    getInfo(3,5) //输出8.会自动匹配function getInfo(num1: number,num2:number): number这个函数
    
    getInfo("你好","世界") //输出你好世界, 会自动匹配getInfo(num1: string,num2: string): string;
    
    注意:在函数重载中,实现函数是不能直接被调用的,如果上面定义的函数都没匹配到,那就会报错
    
    //类
    class Person {
      name: string; //省略了前面public关键词
      age: number;
      // 构造函数,实例化类的时候会触发
      constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
      }
      run() {
        console.log("我是" + this.name + "," + "我在运动");
      }
      //也可以写setter和getter方法
    }
    //创建实例化对象
    let p = new Person("张三", 18);
    console.log(p.age);
    p.run();
    p.name = "小工";
    p.run();
    
    //ts中的继承 extends super
    class Man extends Person {
      aihao: string;
      constructor(aihao: string, name: string, age: number) {
        super(name, age);
        this.aihao = aihao;
      }
      run() {
        console.log(
          "我是" + this.name + "," + "我的爱好是" + this.aihao + "我在运动"
        );
      }
    }
    
    let man = new Man("打游戏", "小k", 18);
    man.run();
    
    //类里面的修饰符
    //ts定义属性的时候给我们提供了三种修饰符
    // public : 公有属性,在类里面 子类 类外面都可以访问
    // private: 私有属性  在类里面可以访问 子类 类外部没法访问
    // protected: 被保护属性  在类里面 子类里面都可以访问 在类外面没法访问
    
    //类中的静态属性 静态方法
    /*
    在es5中定义实例方法和静态方法
    function Animal(){
      // 实例方法
      this.sleep = function(){
        console.log("我爱睡觉")
      }
    }
    实例方法调用: let animal = new Animal() animal.sleep()
    // 静态方法
    Animal.speak = function(){}  
    静态属性 Animal.height = 150
    静态方法调用Animal.speak()
    */
    //在ts中定义静态属性和静态方法
    class Car {
      name: string;
      static color: string = "黑色";
      constructor(name: string) {
        this.name = name;
      }
      // 实例方法
      run() {
        console.log("我是会跑的小车车");
      }
      //静态方法 声明时前面加上static,在静态方法里面没法调用实例属性,因为这里面的this不是实例对象,而是类对象
      static stop() {
        console.log("我的" + this.color + "车子停止了");
      }
    }
    
    let sCar = new Car("小汽车");
    sCar.run(); //实例方法调用
    Car.stop(); //静态方法调用
    
    // 多态 : 父类定义一个方法不去实现,让继承它的子类去实现,每个子类有不同的表现
    
    class Obj {
      name: string;
      constructor(name: string) {
        this.name = name;
      }
      eat() {
        console.log("我定义了一个方法,但我没有具体去实现");
      }
    }
    
    class Obj1 extends Obj {
      constructor(name: string) {
        super(name);
      }
      eat() {
        return "我是Obj1,这是我实现的方法";
      }
    }
    
    class Obj2 extends Obj {
      constructor(name: string) {
        super(name);
      }
      eat() {
        //函数的返回值可以生了不写,会自动推断
        return "我是Obj2,这是我实现的方法";
      }
    }
    
    // 抽象方法
    //在ts中的抽象类:他提供其他类继承的基类,不能直接被实例化
    //用abstract关键字定义抽象类,抽象类中的抽象方法不包含具体的实现并且必须在派生类中实现
    //abstract抽象方法只能放在抽象类里面
    //抽象类和抽象方法用来定义标准
    
    //定义一个车类.要求车子必须会跑
    abstract class Cars {
      //抽象类面可以有非抽象方法,但必须至少包含一个抽象方法
      //父类只定义抽象方法 不实现 等子类实现
      abstract run(): void;
      //抽象类也可以有非抽象方法 子类可以不用实现
      stop() {
        console.log("我的车子刹不住");
      }
    }
    
    //错误的写法  let cars = new Cars()  抽象类无法被实例化
    //继承用extends
    class BigCar extends Cars {
      //抽象类的子类必须要实现抽象方法
      run() {
        console.log("我是一个会跑的车子,我符合标准,我实现了父类的抽象方法");
      }
    }
    
    let bigCar = new BigCar();
    bigCar.run();
    bigCar.stop;
    
    //接口interface
    
    //单个的约束
    //{ name: string }就是对传入数据的约束
    function printInfo(info: { name: string }) {
      console.log("我的名字是=" + info.name);
    }
    printInfo({ name: "张三" });
    //printInfo({ dec: "张三" }); 错误的写法
    
    //如果对很多传入的数据都进行约束 如果按上面的写法会非常麻烦 这时候我们就用到了接口 interface
    
    //属性接口
    //如果传入一个对象,参数必须是字符串,且包含firstName和secondName
    //定义接口
    interface FullName {
      firstName: string;
      secondName: string;
    }
    
    function getPersonalName(name: FullName) {
      console.log(name.firstName + name.secondName);
    }
    getPersonalName({ firstName: "张", secondName: "三" });
    
    //可选属性接口
    /*
    interface 接口名称 {
      接口形参:形参类型;
      接口形式1?:形参类型; //可选属性接口,这个值可传可不传
    }
    */
    
    //函数类型接口:主要对函数的参数个数 参数类型和返回值类型的约束
    interface funcType {
      (a: string, b: string): string;
    }
    
    let funs: funcType = function (name: string, address: string): string {
      return "我的名字=" + name + "," + "我住在" + address;
    };
    console.log(funs("小李", "玉龙山庄"));
    
    //可索引接口:对数组.对象的约束(不常用)
    
    //对数组的约束
    interface customArr {
      // 索引值是number 值为string的接口
      [index: number]: string;
    }
    let arr2: customArr = ["周一", "周二"];
    console.log(arr2);
    
    //对对象约束
    interface customObj {
      [index: string]: string;
    }
    let dic: customObj = { name: "hhh", dec: "jj" };
    console.log(dic);
    
    //类类型接口:对类进行约束
    //定义类面含有的属性,方法等
    interface CustomP {
      name: string;
      speak(word: string): string;
    }
    
    class xiaoP implements CustomP {
      name: string;
      constructor(name: string) {
        this.name = name;
      }
      speak(a: string) {
        return "我的名字叫" + this.name + "我说了句" + a;
      }
    }
    
    let xiaop = new xiaoP("小p");
    console.log(xiaop.speak("我好大"));
    
    //接口的扩展:接口可以继承接口
    //接口继承接口时子接口类除了实现自身约束的内容外还要实现父接口里面的所内容
    interface SmallP extends CustomP {
      age: number;
      dnner(): void;
    }
    class SP implements SmallP {
      name: string;
      age: number;
      constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
      }
      speak(a: string) {
        return "我的名字叫" + this.name + "我今年" + this.age + "岁,我说了句" + a;
      }
      dnner() {
        console.log("我是一个新方法");
      }
    }
    
    let sp = new SP("小红", 18);
    console.log(sp.speak("我是老sp"));
    sp.dnner();
    
    //继承类且实现接口
    //首先需要考虑接口里面的约束要全部实现,同时要考虑要父类有属性时要调用父类初始化器
    class PP {
      name: string;
      constructor(name: string) {
        this.name = name;
      }
      dothings(dec: string) {
        console.log("我爱-->" + dec);
      }
    }
    class ZPP extends PP implements CustomP {
      constructor(name: string) {
        super(name);
      }
      speak(w: string) {
        return "我是zpp" + "我说了句" + w;
      }
    }
    
    let zpp = new ZPP("我是小zpp");
    console.log(zpp.speak("真丑"));
    zpp.dothings("做爱做的事");
    
    //泛型:解决复用性,以及数据类型的多样性
    
    function oneandoneadd<T>(a: T): T {
      return a;
    }
    function oneandoneadd1<T extends string | number>(a: T): T {
      return a;
    }
    console.log(oneandoneadd<string>("你好"));
    console.log(oneandoneadd1(1));
    
    //泛型类
    
    class MinClass<T> {
      list: T[] = [];
      add(value: T) {
        this.list.push(value);
      }
      min(): T {
        let min = this.list[0];
        for (let i = 0; i < this.list.length; i++) {
          if (min > this.list[i]) {
            min = this.list[i];
          }
        }
        return min;
      }
    }
    let m = new MinClass<number>();
    m.add(25);
    m.add(77);
    m.add(10);
    console.log(m.min()); //输出结果10
    
    let m1 = new MinClass<string>();
    m1.add("张");
    m1.add("王");
    m1.add("赵");
    console.log(m1.min()); //输出结果张
    
    //泛型接口
    interface CConfig<T> {
      plus(a: T, b: T): T;
    }
    
    class Con implements CConfig<string> {
      plus(a: string, b: string) {
        return a + "----" + b;
      }
    }
    let con = new Con();
    console.log(con.plus("hello", "world"));
    
    class Non implements CConfig<number> {
      plus(a: number, b: number) {
        return a + b;
      }
    }
    let non = new Non();
    console.log(non.plus(1, 5));
    
    //命名空间 namespace ***  避免命名冲突
    //要注意和模块区分
    namespace A {
      //默认里面的内容是私有的,想在外面使用,用export进行暴漏
      export function srun() {
        console.log("跑起来");
      }
      function curn() {
        console.log("在外部无法调用");
      }
    }
    //调用
    A.srun();
    // A.curn() //报错
    namespace B {}
    
    //装饰器:装饰器就是一个方法,可以注入到类 方法 属性参数来扩展类 属性  方法 参数的功能
    //类装饰器:类装饰器在类声明之前被声明(紧靠着类声明).类装饰器应用于构造函数,可用来监视,修改或替换类定义
    
    //创建一个类装饰器
    function classdec(params: any) {
      console.log(params); //打印出来的params其实就是被装饰的类本身,然后拿着这个类在原型链上可以新增一些属性和方法
      params.prototype.api = "bbbbb"; //在原型链上扩展属性
      params.prototype.requset = function () {
        console.log("我是扩展的方法");
      };
    }
    
    //用@装饰器名字  紧挨着类的声明  装饰器后面不要写分号
    @classdec //普通装饰器
    //定义一个类
    class HttpNet {
      constructor() {}
      getData() {}
    }
    
    let net: any = new HttpNet();
    console.log(net.api); //打印出bbbbb
    net.requset(); //输出我是扩展的方法
    
    //带参数装饰器,装饰器工厂
    function leidec(para: string) {
      return function (target: any) {
        console.log(target);
        console.log(para);
        target.prototype.api = para; //在原型链上扩展属性
        target.prototype.requset = function () {
          console.log("我是扩展的方法");
        };
      };
    }
    
    @leidec("http://www.nnnn") //net赋值给了para  当前的类赋值给了target
    class NetWork {
      run() {}
    }
    
    //类装饰器重载构造函数
    
    function classReload(target: any) {
      return class extends target {
        kk: string = "366666";
        getData() {
          this.atr = this.kk;
          console.log(this.atr);
        }
      };
    }
    
    @classReload
    class MineClass {
      atr: string | undefined;
      constructor() {
        this.atr = "我是梦";
      }
      getData() {
        console.log("我是方法---",this.atr);
      }
    }
    
    //属性装饰器
    function  classAttr(params:string){
      return function(target:any,attr:any){
        console.log(target) //target当前类的原型对象,
        console.log(attr) //当前属性 name
        target[attr] = "" //可以修改类中的属性值
      }
    }
    
    class MClass {
      //装饰url属性
      @classAttr("kkkkkk")
      name:any | undefined
      constructor(){
    
      }
    }
    
    

    相关文章

      网友评论

          本文标题:TypeScript学习笔记

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