typescript笔记

1.什么是 TypeScript
    TypeScript 是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持,它由 Microsoft 开发,代码开源于 GitHub 上。
    
2.TypeScript优点
    1)TypeScript提供了强大类型系统,可以在编译阶段就发现大部分错误
    
3.TypeScript使用
    1) 安装
        npm install -g typescript
    2) 编译
        tsc hello.ts(文件名) 
        tsc 编译全部ts文件
    3) 自动编译ts文件
        1.初始化 tsconfig.json
          tsc --init
        2.下载vscode插件保存文件自动ts代码(有个小问题,一个ts文件会生成一个js文件,生成的文件过多)
            TypeScript Auto Compiler
            
4.数据类型
    1)基本类型:Number、String、Boolean、Null、Undefined、Symbol
        //限制了变量的类型,后面改变变量的值如果类型不一样报错
        let a: number = 123;
        const e: undefined = undefined;
        const f: symbol = Symbol();
    2)联合类型
        // 变量a 可以是number/string/boolean类型
        let a: number | string | boolean =123;    
        
        function fn(x: string | number) {
          // 当我们使用联合类型定义参数
          // 使用参数的属性方法必须是联合类型类型公共的属性方法才行
          // return x.length; // error length属性number没有
          return x.toString(); // ok toString()是公共的方法
        }
        // a中有bc两属性
        type a = {b:string}&{c:string}
    3)数组、元组
        1.数组
            // 1) 「类型 + 方括号」表示法
            const a: number[] = [1, 2, 3];
            // 2) 数组泛型
            const b: Array<string> = ["1", "2"];
        2.元祖
            元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同
            //类型位置不能变,值个数不能多也不能少
            let x: [number, string] = [1, "hello"];        
    4)函数
        1) 函数声明
            // 函数参数xy为number类型,函数返回值为number类型
            function sum(x: number, y: number): number {
              return x + y;
            }
            // 空 函数没有任何返回值
            function sayHello(): void {
              console.log('hello !@');
            }
        2) 函数表达式
            // mySum2为函数类型,参数xy为number类型,返回值为number类型
            let mySum2: (x: number, y: number) => number = function (
              x: number,
              y: number
            ): number {
              return x + y;
            };
        3) 可选参数
            // 我们用 ? 表示可选的参数,可选参数后面不允许再出现必需参数了
            function buildName(firstName: string, lastName?: string) {}
        4) 参数默认值
            function buildName(firstName: string, lastName: string = "Cat") {}
        5) 剩余参数
            // ...rest 的方式获取函数中的剩余参数
            // 注意,rest 参数只能是最后一个参数
            function push(array: any[], ...items: any[]) {
              items.forEach(function (item) {
                array.push(item);
              });
            }
    5)object
        // 对象dataObj有两个属性name和age,对应的类型分别是string和number
        // 使用逗号或分号分割都行
        let dataObj: { name: string; age: number } = {
          name: 'Henry',
          age: 31
        };    
        // 等价于
        let dataObj = {
          name: 'Henry',
          age: 31
        };    
        //简写
        let dataObj: object = {
          name: 'Henry',
          age: 31
        };
        //限制key和value类型
        const accessControlTypeMap: Record<number | string, string> = {
            noValue:'--',
            1:'单元门禁',
            2:'大门门禁',
        }        
    6)其它类型
        1. Any(任意类型)
            let z: any = 123;
            z = "string";
            
            // 等价于
            let o; // 类型推论 --> any
            o = 123;
            o = "string";
        2. Void(空值)
            // 表示函数没有返回值
            function fn(): void {}
          3. never
              never类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never的子类型或可以赋值给never类型(除了never本身之外)。 
              即使 any也不可以赋值给never。通常表现为抛出异常或无法执行到终止点(例如无线循环)
              // never的应用场景 抛出异常
            function error(message: string): never {
              throw new Error(message);
            }            
            // 死循环
            function loop(): never {
              while (true) {}
            }    
            
            // never类型是任何类型的子类型,也可以赋值给任何类型
            let y: number;
            y = (() => :never{
              throw new Error('message');
            })();
        4.枚举
            枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝等。
            enum Color {
              red,
              green,
              blue,
            }
            // 枚举的值默认从0开始,依次增加
            console.log(Color["red"]); // 0
            console.log(Color["green"]); // 1
            console.log(Color["blue"]); // 2
            // 实现了相互赋值
            console.log(Color[0]); // red
            console.log(Color[1]); // green
            console.log(Color[2]); // blue
            ==================================
            enum Color1 {
              red = 3,
              green,
              blue = 1,
            }
            console.log(Color1["red"]); // 3
            console.log(Color1["green"]); // 4,从上一个数值加一
            console.log(Color1["blue"]); // 1                
    7)类
        1.public、protected、private修饰符
            class Person {
              public name: string; // 父类子类实列对象都可以访问
              protected gender: string = '男'; // 父类子类可以访问,实列对象不可以访问
              private age: number = 27; // 只有在父类内部可以访问
              // public username: string相当于在上面写上public username: string,在构造函数写上name: string
              constructor(name: string, public username: string) {
                this.name = name;
                this.username = username;
              }
            
              printAge(age: number) {
                this.age = age;
                console.log(this.age);
                this.setGender(this.gender);
              }
            
              private setGender(gender: string) {
                this.gender = gender;
                console.log(this.gender);
              }
            }
        2.static 修饰词
            定义类的静态属性和方法(可以理解为类的私有属性,不过可以通过类名访问)
            class Person {
              static PI: number = 3.14;
            }
            console.log(Person.PI);
        3.set get修饰词
            用于在类外部修改和设置类的私有属性
            class Person {
              private _name: string = '米斯特吴';
              // 设置私有属性
              set setName(value: string) {
                this._name = value;
              }
            
              // 获取私有属性
              get getName() {
                return this._name;
              }
            }
            let person = new Person();
            // 获取值
            console.log(person.getName);
            // 设置值,是等号的形式,不是括号的形式
            person.setName = '米修在线';
        4.继承extends/super
            // 子类继承父类公开的(public)和受保护的(protected)属性和方法
            // super可以调用父类构造函数
            class Student extends Person {
                  constructor(name: string, username: string, studentId: number) {
                      super(name, username);
                  }
              }
          5.抽象类
              1) 抽象类是不允许被实例化的
            2) 抽象类中的抽象方法必须被子类实现
              abstract class Door {
                name: string;
                constructor(name: string) {
                  this.name = name;
            }
            // 定义抽象方法(没有实现)
            public abstract say(): void;
          }
          
          class ADoor extends Door {
            constructor(name: string) {
              super(name);
            }
            say() {
              console.log("say()");
            }
          }
    8)接口 interface
        1.接口定义
            interface Person {
              age: number; // :号 必须要写的
              sex?: string; // ?: 可选的
              readonly salary: number; // 只读 不能修改
              [propName: string]: any; // 可以添加任意多个,任意类型的属性
            }
            
            let person: Person = {
              age: 28,
              // sex: '男'
              salary: 7000,
              ids: [1, 5, 10]
            };
            
            // interface 可以继承  type不能继承
            // type Person2 = { name: string; age: number };
        2.接口继承
            interface PersonInterface {
              name: string;
            }
            // 继承只能继承一个
            interface Employee extends PersonInterface {
              work: string;
            }
            const employee: Employee = {
              name: '米斯特吴',
              work: '前端开发'
            };
        3.类实现接口
            interface PersonInterface {
              name: string;
            }            
            interface StudentInterface {
              id: number;
            }            
            // 类可以实现多个接口,必须实现必要属性
            class People implements PersonInterface, StudentInterface {
              name: string = '米斯特吴';
              id: number = 101;
            }
        4.接口定义函数和数组形状
            接口定义函数和数组形状时,不能有其它属性,不用写{}号
            interface ArrayList {
              [index: number]: boolean; // 任意属性,也可以当做数组,但是不能有其它属性
            }
             const c: ArrayList = [true, false];
         
            interface SearchFunc {
                // 参数为string类型,返回值为boolean类型
              (source: string, subString: string): boolean;
            }        
            let mySearch: SearchFunc;
            mySearch = function (source: string, subString: string) {
              return source.search(subString) !== -1;
            };
5.泛型
    在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
    1) 在函数中使用泛型
        // identify<T>当前函数支持泛型,可以通过T指定类型
        function identify<T>(arg: T): T {
          return arg;
        }
        console.log(identify<string>('string'));
    2) 在接口中使用泛型
        interface GenericIdentify<T> {
            (arg: T): T;
        }
        function identify<T>(arg: T): T {
            return arg;
        }
        // 接口实现时,如果是一个函数或一个数组可以去掉{}号
        let myIdentify: GenericIdentify<number | string> = identify;
    3) 在类中使用泛型
        class CountNumber<T extends number> {
          number1: T;
          number2: T;        
          constructor(num1: T, num2: T) {
            this.number1 = num1;
            this.number2 = num2;
          }        
          // 泛型中计算要在变量前添加+号
          calcalate(): number {
            return +this.number1 / +this.number2;
          }
        }        
        const countNumber = new CountNumber<number>(10, 20);
        console.log(countNumber.calcalate());
    4) 泛型约束
        // T必须是number类型
        function getLength<T extends number>(obj: T): any {
            return obj;
        }
        // T必须是对象,并且含有length属性
        function getLength<T extends { length: any }>(obj: T): any {
            return obj.length;
        }    

6. type关键字用法
    1)类型别名
        type MyType = { data: number[]; myfunc: (item: number) => number[] };
        let complex2: MyType = {
          data: [1, 2, 34],
          myfunc: function(item: number): number[] {
            this.data.push(item);
            return this.data;
          }
        };    
    2)字符串字面量类型
        字符串字面量类型用来约束取值只能是某几个字符串中的一个。
          type Mode = 'development' | 'production' | 'none';
          // mode的值只能是'development' 或 'production' 或 'none'
          function fn(mode: Mode) {
            console.log(mode);
          }
        
7.检查类型、类型推论、断言
    1)检查类型
        let checkType = 10;
        // 检测的结果必须用引号包起来
        if (typeof checkType == 'number') {
          console.log('number');
        }
    2)类型推论        
        // 正常
        let a: number = 123;
        // 类型推论: 推论为number类型,相当于let b: number = 123
        let b = 123;     
        // 类型推论: 推论为any类型
        let c; 
        c = 123;
        c = 'string';
    3)断言
        1. 语法
            值 as 类型
            <类型>值
            在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用前者,即 值 as 类型。
            故建议大家在使用类型断言时,统一使用 `值 as 类型` 这样的语法。
        2.用途
            1)将一个联合类型断言为其中一个类型
                interface Cat {
                  name: string;
                  run(): void;
                }
                interface Fish {
                  name: string;
                  swim(): void;
                }
                
                function isFish(animal: Cat | Fish) {
                  if (typeof (animal as Fish).swim === "function") {
                    return true;
                  }
                  return false;
                }
            2)将一个父类断言为更加具体的子类
                class ApiError extends Error {
                  code: number = 0;
                }
                class HttpError extends Error {
                  statusCode: number = 200;
                }
                
                function isApiError(error: Error) {
                  if (typeof (error as ApiError).code === "number") {
                    return true;
                  }
                  return false;
                }                        
8.命名空间
    类似于局部作用域,用来防止命名冲突问题
    1)命名空间的定义
        // 通过namespace命名一块空间,export暴露出去,外包可以通过MyMath+.的方式访问
        namespace MyMath {
              export const PI = 3.14;
              export function sumValue(num1: number, num2: number): number {
                return num1 + num2;
            }
        }
        console.log(MyMath.sumValue(15, 10));
        console.log(MyMath.PI);
    2)命名空间多文件分离
        //控制台输出如下命令 将circle.ts sumValue.ts app.ts文件打包成一个app.js文件输出
        tsc --outfile app.js circle.ts sumValue.ts app.ts
    3)多重命名空间和引入文件
        1.多重命名空间
            namespace MyMath {
              export namespace Circle {
                const PI = 3.14;
            
                export function calcCircle(value: number) {
                  return value * PI;
                }
              }
            }
            console.log(MyMath.Circle.calcCircle(8));
        2.引入文件
            // 三个斜杆代表开始要引入文件
            /// <reference path="sumValue.ts" />
            
9.模块化
    1)暴露模块
        // 分别暴露
        export const PI = 3.14; 
        // 默认暴露
        export default function sumValue(num1: number, num2: number): number {
          return num1 + num2;
        }
    2)引入模块
        // 分别暴露的引入方式
        import { PI, calcCircle } from './stuff/circle';
        import * as Circl from './stuff/circle';
        // 统一暴露的引入方式
        import sum from './stuff/sumValue';
    3)模块化编译后的语法浏览器无法识别,需要在index.html文件中做以下配置
        // system.js版本文2以下
        <script src="https://cdn.bootcss.com/systemjs/0.21.5/system.js"></script>
        System.config({
          baseUrl: '/',
          packages: {
            '/': {
              defaultExtension: 'js' //让浏览器识别js文件
            }
          }
        });    
        System.import('app.js');
10.其它
        1)声明文件
            当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。
            声明语句: 如果需要ts对新的语法进行检查, 需要要加载了对应的类型说明代码
                  declare var jQuery: (selector: string) => any;
            声明文件: 把声明语句放到一个单独的文件(jQuery.d.ts)中, ts会自动解析到项目中所有声明文件
            下载声明文件: npm install @types/jquery --save-dev
        2)内置对象
              // let b: Boolean = new Boolean(1)
              // let n: Number = new Number(true)
              // let s: String = new String('abc')
              // let d: Date = new Date()
              // let r: RegExp = /^1/
              // let e: Error = new Error('error message')    
              // boolean应该换成Boolean
              // let bb: boolean = new Boolean(2)  // error
              
              const div: HTMLElement = document.getElementById('test')
              const divs: NodeList = document.querySelectorAll('div')
              document.addEventListener('click', (event: MouseEvent) => {
                console.dir(event.target)
              })
              const fragment: DocumentFragment = document.createDocumentFragment()    
        3)Partial
            interface IUser {
                name: string
                age: number
                department: string
            }
            type optional = Partial<IUser>
            // optional的结果如下
            type optional = {
                    name?: string | undefined;
                    age?: number | undefined;
                    department?: string | undefined;
            }
        4)Omit
            Omit<K,T>类型让我们可以从另一个对象类型中剔除某些属性,并创建一个新的对象类型:
            K:是对象类型名称,T:是剔除K类型中的属性名称
            type  UserProps =  {
                name?:string;
                age?:number;
                sex?:string;
            }
            // 但是我不希望有sex这个属性我就可以这么写
            type NewUserProps =  Omit<UserProps,'sex'> 
            // 等价于
            type  NewUserProps =  {
                name?:string;
                age?:number;
            }
        5)ts类型中的&
            type Env1 = 'prod' | 'test' | 'dev';
            type Env2 = 'prod' | 'boe' | 'ppe';
            type EnvInter = Env1 & Env2; // 'prod'
        6)ts类型中的??
            //a为undefind或者null时返回b
            a??b
        

        
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值