flow 的基本使用

272 阅读3分钟

1. 强类型和弱类型

  • 强类型和弱类型(类型安全)
    • 强类型
      • 语言层面限制函数的实参类型必须与形参类型相同
      • 有更强的类型约束
      • 不允许随意的隐式类型转换
      • 优势
        • 错误会更早暴漏
        • 代码更智能,编码更准确
        • 重构会更可靠
        • 减少不必要的类型判断
    • 弱类型
      • 几乎没有类型约束
      • 允许随意的隐式类型转换
  • 静态类型和动态类型(类型检查)
    • 静态类型
      • 一个变量声明时类型就是确定的
      • 变量声明过后类型不允许再修改
    • 动态类型
      • 在运行阶段才能明确变量的类型
      • 变量的类型可以随时发生改变

2. flow

  • 安装 flow yarn add flow-bin --dev

  • flow 上手

    • 安装 flow,yarn add flow-bin --dev
    • 添加 flow 注解
    • 初始化 flow 配置文件 .flowconfig,yarn flow init
    • 运行 flow,yarn flow
    • 停止 flow 服务,yarn flow stop
    // @flow
    function sum(a: number, b: number) {
      return a + b
    }
    sum(100, 200)
    sun('100', '200')
    
  • flow 编译移除类型注解

    • 使用官方的模块 flow-remove-types

      • 安装 flow-remove-types,yarn add flow-remove-types --dev

      • 运行 flow-remove-types,yarn flow-remove-type .(当前目录) -d dist(输出目录)

      • 移除类型注解的代码

        //      
        function sum(a        , b        ) {
          return a + b
        }
        
        sum(100, 200)
        
        sum('100', '200')
        
    • 使用 babel

      • 安装 babel,yarn add @babel/core(babel 的核心模块) @babel/cli(babel 的 cli 工具) @babel/preset-flow(转换 flow 类型注解的插件) --dev

      • 在项目根目录添加 .babelrc 配置文件

        {
          "presets": ["@babel/preset-flow"]
        }
        
      • 运行 babel,yarn babel .(当前目录) -d dist(输出目录)

      • 移除类型注解的代码

        function sum(a, b) {
          return a + b;
        }
        
        sum(100, 200);
        sum('100', '200');
        
  • 类型推断

    • 根据代码中使用情况,推断出变量的类型
  • 类型注解

    /**
     * 类型注解
     * @flow
     */
    
    // 给参数设置类型
    function square(n: number) {
      return n * n
    }
    
    // 给变量设置类型
    let num: number = 100
    
    // 给函数返回值设置类型
    // 对于没有返回值的函数,可以将返回值类型标记为 viod
    function foo(): number {
      return 100
    }
    
  • 数据类型

    • 原始类型

      /**
       * 原始类型
       * @flow
       */
      
      const a: string = '123' // 字符串
      const b: number = 123 // 数字, NaN, Infinity
      const c:boolean = true // true, false
      const d: null = null // null
      const e: void = undefined // 用 void 表示 undefined
      const f: symbol = Symbol()
      
    • 数组类型

      /**
       * 数组类型
       * @flow
       */
      
      const arr1: Array<number> = [1, 2, 3]
      const arr2: number[] = [1, 2, 3]
      
      // 表示固定长度的数组,可以用数组字面量的方式 === 元组
      const foo: [number, string] = [1, 'string']
      
    • 对象类型

      /**
       * 对象类型
       * @flow
       */
      
      // 定义的成员必须都拥有
      const obj1: { name: string, age: number } = { name: 'kjy', age: 24 }
      // 设置可选成员
      const obj2: { name: string, age?: number } = { name: 'kjy' }
      
      // 作为键值对集合使用
      const obj3: { [string]: string | number } = {}
      
      obj3.name = 'kjy'
      obj3.age = 24
      
    • 函数类型

      /**
       * 函数类型
       * @flow
       */
      
      // 对于参数的限制
      function foo(a: number, b: number) {
        return a + b
      }
      
      // 对于返回值限制
      function foo(a: number, b: number): number {
        return a + b
      }
      
      // 对于回调函数的限制
      function foo(callback: (string, number) => void) {
        callback('string', 100)
      }
      
    • 特殊类型

      /**
       * 特殊类型
       * @flow
       */
      
      // 字面量类型
      
      const a: 'foo' = 'foo'
      
      const type: 'success' | 'warning' | 'danger' = 'success'
      
      // 或类型
      const b: string | number = 'string' // string, number
      
      // 声明类型,用 type 关键词声明一个类型
      type StringOrNumber =  string | number
      
      const c: StringOrNumber = '100'
      
      // 可以为空
      // ?string === string | null | undefined
      const d: ?string = null // string, null, undefined
      
    • mixed 和 any

      • mixed 是强类型,必须明确数据类型
      • any 是弱类型
      /**
       * mixed and any
       * @flow
       */
      
      // mixed 类型是所有类型的联合类型
      function foo(value: mixed) {
        // 明确数据类型
        if (typeof value === 'number') {
          value * value
        }
      
        if (typeof value === 'string') {
          value.substr(1)
        }
      }
      
      
      // any 类型可以接收所有类型
      function bar(value: any) {
        value.substr(1)
      
        value * value
      }