美文网首页
Typescript入门学习

Typescript入门学习

作者: 大佬_娜 | 来源:发表于2020-11-19 16:31 被阅读0次

    1. 编程语言的类型 : 动态类型语言 和 静态类型语言(c\ C++ \Jave)

    2. Typescript 是什么 ?

      1.  是通过在JavaScrip的基础上添加了静态类型风格的类型系统
      2.  对es6到es10的预发支持,兼容各种浏览器
    

    3. 为什么要使用Typescript

    优点:

    • 程序容易理解 定义函数或者方法输入输出的参数类型可容易理解程序
    • 效率更高 ,通过ide代码可自动补全、自动识别错误信息
    • 包容性好 , 完全兼容JavaScript
      缺点:
    • 学习成本高
    • 短期增加了一些开发成本

    4. 安装typescript

     node版本12.5.0 ,建议 10以上,  npm 版本6.9.0  ,tsc 版本3.8.3
     ts-node XXX.ts  执行ts,输出结果
     tsc  XXX.ts    编译ts为js文件
    

    5. Typescript数据类型

    原始数据类型 string、boolean、number、undefined 、null

          注意 undefined 和 null 是所有类型的子类型,可以随意赋值给其它数据类型。
          let  flag :boolean = true
          let   issure: any = 123    // 不确定数据类型用法
          issure = "abc"
    

    复杂数据类型 数组array 和元组 tuple

            let arr1: number[] = [12, 2, 34]
            let arr2: [number, string] = [123, 'abc']
    

    interface接口 针对object进行约束

            interface IPerson {
                  readonly id : number;    //readonly  只读不可编辑
                  age ? : number,             // ?     IPerson   age属性可有可无
                  name : string
              }
            let na : IPerson = {
                  id:1,
                  age : 2 , 
                  name: 'nana'
            }
    

    interface接口 针对function输入输出约束

        interface ISum {
          (x:number,y:number,z ?: number) :number
        }
        let add :ISum = (x:number,y:number,z ?:number):number => {
              if( typeof z === 'number'){
                        return x + y + z
              }else{
                       return x + y
              }    
        }
        add(1,2,3)
    

    6. 类型推断 联合类型 类型断言

    let  num =  123;    //  num 此时类型被推断为 number类型,不可修改为其他类型
    
    //联合类型 union types : 不确定一个类型的变量到底是哪个类型的时候 ,只需要用中竖线来分割两个类型,此时只能访问此联合类型的所有类型里共有的属性或方法:
    let numberOrstring: number | string;
    numberOrstring = 123;
    numberOrstring = 'abc';
    
    
    //类型断言  可以用 as 关键字,告诉typescript 编译器参数。
    function getLength(input : number | string) :number {
      const inp = input as string;
      if(inp.length){
          return inp.length
      }else{
          const num = input as  number;
          return num.toString().length
      }
    }
    
    

    7. Class 类

    在JavaScript 使用构造函数 原型链实现继承;
    Es6出现Class概念,内部使用原型链机制实现 ,有了面向对象的概念;
    面向对象基本术语:

    • 类(class) :定义了一切事物的抽象特点
    • 对象 (Object) : 类的实例,通过New生成
    • 面向对象 (OOP) 三大特性:封装 、继承、多态
      封装: 将数据操作细节隐藏起来,对外只暴露接口,只通过接口访问该对象。 创建一个Animal类
    class Animal {
      constructor(name){
          this.name = name;
      }
      run(){
        return `${this.name} is running`
      }
    }
    const snake = new Animal('snake')
    console.log(snake.run())
    

    继承: 子类可以继承父类的特征 。通过extends继承

    class Dog extends Animal{
        eat(){
            return `${this.name} is eatting`
         }
    }
    const kele = new Dog('kele')
    console.log(kele.run())
    console.log(kele.eat())
    

    多态: 通过继承,子类也可以拥有自己的方法。

    class Cat extends Animal{
      static cate = ['cateqqq']   //静态属性、方法,与实例没有太大的关系
      construcor(name){
        super(name)   //重写构造函数需要使用super方法
      }
      run(){
        return 'Hi,' + super.run()   //调用父类方法需要使用 super关键字
      } 
    }
    const maomao = new Cat('maomao')
    console.log(maomao.run())
    console.log(Cat.cate )
    

    Typescript中的class
    3种访问修饰符 ,类上的属性和方法添加权限管理

    • Public :修饰的属性和方法是共有的,可以在任何地方被调用到,默认使用的
    class Animal {
        name: string;
        constructor(name) {
            this.name = name;
        }
        run() {
            return `${this.name} is running`
        }
    }
    const snake = new Animal('snake')
    console.log(snake.run())
    
    • private : 修饰的属性和方法是私有的,子类也不可以访问和修改
    class Animal {
        name: string;
        constructor(name) {
            this.name = name;
        }
       private  run() {
            return `${this.name} is running`
        }
    }
    const snake = new Animal('snake')   
    console.log(snake.run())  //报错  属性'run'为私有属性,只能在类'Animal '中访问
    
    • Protected: 修饰的属性和方法是受保护的,子类可以访问
    • readonly : 只能读 不可以写
    class Animal {
        readonly   name: string;
        constructor(name) {
            this.name = name;
        }
        protected run() {
            return `${this.name} is running`
        }
    }
    class Cat extends Animal {
        construcor(name) {
            super(name)   //重写构造函数需要使用super方法
        }
        run() {
            return 'Hi,' + super.run()   //调用父类方法需要使用 super关键字
        }
    }
    const maomao = new Cat('maomao')
    console.log(maomao.run())
    

    8. 类和接口 搭档使用

    interface 用于对对象的形状进行描述,描述函数的类型,对类的一部分形为进行抽象。

    • 继承困境 : 一个类只能继承自另外一个类,不同类之间需要有共同的特性,使用子类调用父类的方法不太合适。
    • 特性提取成接口,用一个 implements关键字来实现接口,提高面向对象的灵活性。
    //特性1 :收音机
    interface Radio {
        switchRadio(trigger: boolean): void     //void关键字代表什么也不返回
    }
    //特性2 :检查电池容量
    interface Checkbox {
        checkBoxStatus(): void
    }
    //特性3 : 接口之间的继承   RadioWithCheckbox 接口继承Radio  ,即有开关收音机又有检查电池容量
    interface RadioWithCheckbox extends Radio {
        checkBoxStatus(): void
    }
    class Car implements Radio {
        switchRadio(trigger: boolean) {
        }
    }
    //可写为 class Mobile implements Radio ,Checkbox   ,也可以写为 :
    class Mobile implements RadioWithCheckbox {
        switchRadio(trigger: boolean) {
        }
        checkBoxStatus() {
        }
    }
    

    9. 枚举 enums

    枚举: 指的是常量情况,执行程序不会改变 ,在js中用const , 取值在一定范围内的一系列常量,例 一周7天; 这种情况需要用枚举表示

    //数字枚举
    enum Direction {
        Up,   //0       Up也可手动赋值 10, 下面会自动递增  Up = 10
        Down, //1
        Left, //2
        Right //3
    }
    
    console.log(Direction.Up)   //返回0
    console.log(Direction[0])   //返回Up
    
    //字符串枚举 ,提升性能  编译代码简单
    enum DirectionS {
        Up = 'UP',
        Down = 'DOWN',
        Left = 'LEFT',
        Right = 'RIGHT'
    }
    const value = 'UP'
    if (value === DirectionS.Up) {
        console.log('go up!')
    }
    

    10. 泛型 Generics

    泛型 指定义函数 接口或 类的时候不予先指定具体类型,而是在使用的时候在指定类型的一种特征

    //泛型定义进阶1
    function echo(arg) {
        return arg
    }
    const result = echo(123)   //发现返回结果为any类型,变量丧失了类型
    //泛型定义进阶2
    function echo1(arg: number): number {
        return arg
    }
    const result1 = echo1(123)    // echo1返回number类型,但需求有可能传入各种类型,满足不了需求
    //泛型定义进阶3
    function echo2(arg: any): any {
        return arg
    }
    const result2: string = echo2(123)    //丧失类型,返回any类型,还存在一个问题,传入和返回的值无法做到统一,返回any类型,传入的string类型 属于any下的类型 
    
    //泛型使用generics 占位符传入1个参数
    function echo3<T>(arg: T): T {
        return arg
    }      
    const result3 = echo3(123)  //传入数字123,通过类型推断,返回数字类型
    
    //泛型使用generics 占位符传入元组
    function swap<T, U>(tuple: [T, U]): [T, U] {
        return (tuple[0], tuple[1])
    }
    const result4 = swap(['string', 123])
    

    约束泛型

    // 泛型约束进阶1
    function echoWithArr<T>(arg: T): T {
        console.log(arg.length)  //报错,类型T上不存在length属性,所以得对泛型做约束
        return arg;
    }
    
    //泛型约束进阶2 
    function echoWithArr1<T>(arg: T[]): T[] {
        console.log(arg.length)
        return arg;
    }
    const arrs = echoWithArr1([1, 2, 3])   //返回正确的number数组,处理并不完美, string和对象都可能有length属性
    // const str = echoWithArr1('str')      //返回报错,string类型参数不能赋值给元组[]类型
    
    
    //进行约束,只允许这个函数传入包含length属性的变量,新建一个interface ,包含length属性  
    
    interface Iwithlength {
        length: number
    }
    //使用extends关键字约束传入的泛型,只返回传入的参数有length属性
    function echoWithLength<T extends Iwithlength>(arg: T): T {
        console.log(arg.length)
        return arg
    }
    const str1 = echoWithLength('str')
    const obj1 = echoWithLength({ length: 10 })
    const arrs2 = echoWithLength([1, 2, 3, 4])
    const num = echoWithLength(10)   //错误,类型number的参数不能赋值给Iwithlength的参数
    

    类泛型约束

    // 类泛型进阶1
    class Queue {
        private data = [];
        push(item) {
            return this.data.push(item)
        }
        pop() {
            return this.data.shift()
        }
    }
    const queue = new Queue()
    queue.push(1)
    queue.push('str')
    console.log(queue.pop().toFixed())   //删除第一个元素并返回1  ,数字1可以使用toFixed方法
    console.log(queue.pop().toFixed())   //ts不报错,但是编译js后会报错,  string类型不可以使用toFixed方法
    
    //类泛型约束  解决上诉问题 ,无论什么类型被推入队列 , 推出的类型和推入类型一致
    class Queue1<T>{
        private data = [];
        push(item: T) {
            return this.data.push(item)
        }
        pop(): T {
            return this.data.shift()
        }
    }
    const queue1 = new Queue1<number>()
    queue1.push(1)
    queue1.push('sre')    //报错类型string的参数不能赋值给类型number的参数
    console.log(queue1.pop().toFixed())
    

    泛型在interface的应用

    interface Keypair<T, U> {
        key: T
        value: U
    }  //key,value 的值动态传入
    let kp1: Keypair<number, string> = { key: 1, value: 'str' }
    let kp2: Keypair<string, number> = { key: 'str', value: 1 }
    let kp3: Keypair<string, number> = { key: 1, value: 2 }  //报错 不能将key的类型number传入 string类型
    

    泛型表示number数组类型

    let arr1: number[] = [12, 2, 34]
    let arr2: Array<number> = [1, 2, 3]
    

    11.类型别名、字面量 、交叉类型

    • 类型别名type-aliase
    let sum: (x: number, y: number) => number
    const result = sum(1, 2)
    
    //每次写入繁杂,可使用type关键字创建类型别名
    type PlusType = (x: number, y: number) => number
    let sum2: PlusType
    const result2 = sum2(2, 3)
    //也可使用type创建联合类型
    type StrOrNum = string | number
    let result3: StrOrNum = 'abc'
    result3 = 124
    
    • 字符串 字面量 ,可以提供非常方便的一系列常量写法
    const str: 'name' = 'name'
    const number: 2 = 2
    type Directions = 'Up' | 'Down' | 'Left' | 'Right'
    let toWhere: Directions = 'Left'
    
    • 交叉类型
    interface IName {
        name: string
    }
    type IPerson = IName & { age: number }
    let person: IPerson = { name: 'a', age: 27 }
    

    12.声明文件

    使用第三方库的时候,第三方库不是通过typescript写的 ,直接使用jQuery('#foo')报错,需要通过declare var 声明

    declare var jQuery: (selector:string) = > any ;   
    //声明语句,仅仅全局定义jquery的类型,编译时的检查,最简单的声明文件写法
     jquery.d.ts    //声明语句放到声明文件中
    
    使用第三库的typescript社区 :,可直接安装它的类型文件 
    [社区地址] (https://www.typescriptlang.org/dt/search?search=)
    
    

    13.内置类型

    在ts中可以随意使用最新的JavaScript语法

    • 默认内置类型
    //global objects
    const arr: Array<number> = [12, 23, 3]
    const date = new Date()
    date.getTime()
    const reg = /abc/
    reg.test('as')
    Math.pow(1, 2)
    //Dom and Bom
    let body = document.body;
    let allLis = document.querySelectorAll('li')
    allLis.length
    document.addEventListener('click', (e) => {
        e.preventDefault()
    })
    
    //Partial   把传入的类型可变成可选
    interface Iperson {
        name: string
        age: number
    }
    let viking: Iperson = { name: 'na', age: 12 }
    type Ipartial = Partial<Iperson>   // Iperson的参数都变为可选参数
    let viking2: Ipartial = {}
    
    // Omit 可以忽略传入的某个属性
    type Iomit = Omit<Iperson, 'name'>   //忽略name属性
    let viking3: Ipartial = { age: 12 }
    

    相关文章

      网友评论

          本文标题:Typescript入门学习

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