美文网首页
学习笔记(五)——TypeScript 语言

学习笔记(五)——TypeScript 语言

作者: 彪悍de文艺青年 | 来源:发表于2020-08-29 20:23 被阅读0次

最近参加拉勾教育大前端高薪训练营,开始对前端知识体系进行一个系统的扩展跟学习,通过每天定期的学习,对一些不常使用的知识点进行了了解和补充,同时对已经使用过的知识点温故而知新
在此记录学习笔记,并根据学习进度定时跟新

强类型与弱类型(类型安全维度)

语言层面限制

  • 强类型:不允许任意的数据隐式类型转换
    • 在编码阶段就能提示类型错误,可以更早暴露错误
    • 可以提高代码效率和准确性(可以提供更准确的智能提示)
    • 使重构更便捷可靠
    • 可以减少不必要的类型判断
  • 弱类型:允许任意的数据隐式类型转换
    • 只能在代码运行阶段才能发现问题
  • JavaScript是弱类型语言,Python是强类型语言

静态类型与动态类型(类型检查维度)

  • 静态类型:变量类型在声明时确定,之后不允许再修改
  • 动态类型:变量在运行阶段才能确定,且可以进行修改
  • JavaScript是动态类型语言,Python是动态类型语言

解释型与编译型

  • 解释型:代码运行时解析执行(脚本语言)
  • 编译型:需要预先编译,再执行编译输出的可执行文件

JavaScript类型系统特征

JavaScript是动态类型 弱类型 解释型脚本语言

Flow

由Facebook于2014年推出的JavaScript的类型检查器

  • 安装

    • yarn add flow-bin --dev
    • yarn flow init 初始化flow并生成配置文件 .flowconfig
  • 使用

    • 在JS文件开头添加注释 //@flow
    • 在相应的变量、参数后添加类型注解(冒号及类型)
    • 执行 yarn flow 检查
      • 会启动后台服务监控JS文件
    • 执行 yarn flow stop 停止后台服务
  • 编译移除类型注解

    • flow-remove-types

      • yarn add flow-remove-types --dev 安装
      • yarn flow-remove-types src -d dist 指定路径输出编译移除后的JS文件
    • babel

      • yarn add @babel/core @babel/cli @babel/present-flow 安装

      • 添加配置文件.babelrc

        {
            "presents": ["@babel/present-flow"]
        }
        
      • yarn babel src -d dist 指定路径输出编译移除后的JS文件

  • 开发工具插件

    • VSCode插件:flow-language-support
    • 其他IDE插件支持情况查看flow官网的编辑器支持
  • flow类型推断

    • 可以根据代码实际使用情况自行推断变量的类型,而可以不指明类型注解
  • flow类型注解

    • 在相应的变量、参数后添加冒号及类型
  • flow的类型

    • 原始类型
      • string
      • number
      • boolean
      • null
      • undefined
        • 使用void表示
      • symbol
    • 数组类型
      • Array<number>
      • number []
      • [string, number] :元组
    • 对象类型
      • { foo?: string, bar: number }
        • 限制必须存在特定属性,并限定该属性的类型
        • 属性名加问号,表示该属性可选,如果存在该属性,则属性类型必须为指定的类型
      • { [string]: string }
        • 限制对象key-value键值对类型,不限制属性数量
    • 函数类型
      • (string, number) => void
        • 指定参数及返回值类型
    • 特殊类型
      • 字面量类型:a: 'foo' = 'foo'
        • 限定变量值只能是特定值
      • 联合类型:使用 | 分隔多个类型
        • 字面量类型联合:type: 'success' | 'warning' | 'danger' = 'success'
          • 限定只能是特定可选值之一
        • 类型联合:a: string | number = 100
          • 限定只能是可选类型之一
      • 类型别名
        • type StringNumber = string | number
        • a: StringNumber = 'string'
      • maybe类型
        • 类型前加问号 a: ?number = undefined
        • 等同于 a: number | null | void
    • Mixed与Any
      • 可以接收任意类型
      • Mixed:强类型
        • 虽然可以接收任意类型,但是需要先明确变量是什么类型,才能进行相应的使用
      • Any:弱类型
        • 接收任意类型,并可以任意进行使用
        • 主要为了用来兼容未进行强类型校验的老代码
  • 运行环境API

TypeScript

TypeScript是JavaScript的超集,在JavaScript基础上扩展了类型系统ES6+新特性

  • 优点:

    • 类型系统使代码可靠性更高,同时可以使用ES6+新特性
    • 兼容性好,可以在任何使用JavaScript开发的环境使用TypeScript
    • 生态健全、完善
    • 渐进式,可以只使用部分特性
  • 缺点:

    • 增加了很多概念,例如:接口、枚举、泛型
    • 需要编写大量类型声明,对小型项目会增加开发成本
  • 安装

    • yarn add typescript --dev
  • 执行

    • yarn tsc typescript.ts
      • 编译 typescript.ts 为 typescript.js 文件
      • 进行类型检查
      • 移除类型注解
      • 转换ES6+语法为ES3语法
  • 配置文件

    • yarn tsc --init 初始化创建配置文件 tsconfig.json
    • 配置项
      • target
        • 指定转换为什么版本的ES标准代码
        • 不设置默认es3,配置文件默认es5,其他可选 es2015/es2016/es2017/...
      • module
        • 模块化标准
        • 默认commonjs、其他可选 amd/umd/es2015/es2020/...
      • sourceMap
        • 源代码映射,生成sourceMap,便于代码调试
      • outDir
        • 指定编译结果输出目录
        • 可以配置dist
      • lib
        • 指定标ts准库(ES对应版本内置对象的声明文件),接收一个数组
  • rootDir
    + 指定代码根目录
    + 可以配置src
    + strict
    + 开启严格模式

    • 使用 yarn tsc 直接运行
  • 原始类型

    • string
      • const a: string = 'hello'
      • 非严格模式可以是null或undefined
    • number
      • const b: number = 123
      • 包含 NaN Infinity
      • 非严格模式可以是null或undefined
    • boolean
      • const c: boolean = true
      • 非严格模式可以是null或undefined
    • void
      • const d: void = undefined
      • 标记函数返回类型
      • 非严格模式可以是null
    • null
      • const e: null = null
    • undefined
      • const f: undefined = undefined
    • symbol
      • const g: symbol = Symbol()
      • 需要配置target: es2015以上,或者配置lib引入es2015标准库
  • 强制使用中文显示错误消息

    • yarn tsc --locale zh-CN
    • 修改VSCode setting中相关的配置
    • 建议还是使用英文方式显示,便于问题查询定位
  • 作用域问题

    • 全局作用域下同名变量不能重复定义,可以放到函数作用域中,或者添加export {} 放到模块作用域下
  • Object类型

    • const foo: object = {} // [] // function() {} 可以接受数组、函数、对象
    • const obj: { name: string, value: number} = { name: 'hello', value: 123}
      • 强制对象类型的声明,可以使用对象字面量 {} 的方式,同时可以限制允许出现的属性
      • 使用接口定义更合适
  • 数组类型

    • const array: Array<number> = [1, 2, 3]
    • const array: number[] = [1, 2, 3]
  • 元组类型

    • 元组是一种明确元素数量和类型的特殊数组
    • const tuple: [number, string] = [123, '456']
    • 可以用来在一个函数中返回多个返回值
  • 枚举类型

    • enum关键字定义枚举类型

      enum Status {
          valid = 0,
          invalid
      }
      
    • 枚举值使用等号=赋值

    • 如果不指定枚举值,则默认从0开始,依次递增

    • 如果指定枚举值为数字,则默认依次递增

    • 如果指定一个枚举值为字符串,则需要指定所有它之后的所有枚举的初始的值

    • 枚举类型会被编译为双向键值对对象,可以使用key获得value,也可以使用value获得key

      var Status;
      (function (Status) {
          Status[Status["valid"] = 0] = "valid";
          Status[Status["invalid"] = 1] = "invalid";
      })(Status || (Status = {}));
      
    • enum关键字前增加const时为常量枚举,常量枚举不可以使用枚举值访问枚举的key

  • 函数类型

    • 函数声明形式

      function say (name: string, value: number, ...rest: number[]) : string {
          return `hello ${name}`
      }
      
    • 函数表达式形式

      const said: (name: string, value: number, ...rest: number[]) => string = (name: string, value: number, ...rest: number[]): string => {
          return `hello ${name}`
      }
      

      函数表达式将函数赋值给一个变量,需要给变量一个函数类型,使用箭头函数的形式

  • 任意类型

    • any类型
      • 不会进行类型检查
      • 用来兼容JS老代码
      • 存在类型安全问题
  • 隐式类型推断

    • 由typescript自行推断变量的类型
    • 建议给每个变量添加明确的类型
  • 类型断言

    • 当typescript无法明确推断变量的类型时,可以使用as关键字告诉typescript变量是什么类型
    • 也可以使用 <number> 尖括号<类型>的方式,但跟jsx混合使用的时候,会跟html标签混淆,建议使用as
  • 接口

    • 使用interface关键字定义接口,用来约束对象的结构

      interface Post {
          name: string
          value: number
          desc?: string
          readonly url: string   
      }
      
    • 属性名后加问号,表示可选属性,可选属性外的其他属性必须存在

    • 属性名前加readonly关键字,表示只读属性,初始化后不可修改

    • 不能包含接口定义外的其他属性

  • 面向对象编程中的概念,用来描述具体对象的抽象成员

    ES6以前,使用构造函数+原型的方式实现面向对象的类与继承

    ES6以后,提供了标准化的class来定义类

    typescript增强了class的相关语法(访问修饰符、抽象类等)

    • 基本使用

      • class关键字定一个一个类

      • 在类中声明属性,并初始化(定义时赋值,或在构造函数constructor中初始化)

        class Person {
            name: string
            age: number = 18
            constructor(name: string, age: number) {
                this.name = name
            }
        }
        
    • 访问修饰符

      控制类中属性和方法的访问级别

      • public: 默认
      • private: 无法被类的实例访问
        • 如果constructor被private修饰,将不能使用new实例化
      • protected: 无法被类的实例访问,可以在子类中访问
    • 只读属性

      • readonly关键字修饰类的属性
      • 只能在定义或者构造函数中初始化,之后不能被修改
    • 类与接口

      • 同样使用interface定义接口

      • 在interface中定义类的方法,但不提供实现

      • class使用implements关键字实现一个或多个接口,必须包含接口中定义的方法的实现

        interface Eat {
            eat(food: string): void
        }
        interface Run {
            run(speed: number): void
        }
        class Dog implements Eat, Run {
            eat(food: string) {
                console.log(food)
            }
            run(speed: number) {
                console.log(speed)
            }
        }
        
    • 抽象类

      • 使用abstract关键字定义抽象类

        • 抽象类不能被new实例化,只能被继承
      • 使用abstract关键字定义抽象类的抽象方法

        • 抽象方法不能具有实现
        • 子类继承后必须实现抽象方法
        abstract class Animal {
            eat(food: string): void {
                console.log(food)
            }
            abstract run(speed: number): void
        }
        
        class Cat extends Animal {
            run(speed: number): void {
        
            }
        }
        const cat = new Cat()
        cat.eat('food')
        
    • 泛型

      • 函数定义后使用<T>定义泛型,参数的类型可以被指定为T

      • 函数使用时在函数名后使用<类型>指明具体的类型,以此使函数在使用时可以传入不同类型的参数

        function hey<T>(value: T) {
            console.log(value)
        }
        hey<string>('123')
        hey<number>(123)
        
    • 类型声明

      • declare关键字进行类型声明
      • 使用第三方库时,如果没有提供类型声明文件,需要安装相应的类型声明模块
      • 类型声明模块应该是开发依赖

相关文章

网友评论

      本文标题:学习笔记(五)——TypeScript 语言

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