Flow(二)—— 简单语法使用

目录

  • Flow类型推断
  • Flow类型注解使用的地方
  • Flow Type Annotations
    • 类型参考网址
    • 原始类型
    • 数组类型
      • 元组 —— Tuple Types
    • 对象类型
      • 通用写法
      • 添加可选属性
      • Map类
      • 混合使用
    • 函数类型
      • 函数参数
      • 可选函数参数
      • Rest参数
      • 函数返回
    • 特殊类型
      • 字面量类型
      • maybe类型
    • Mixed 与 Any
      • Mixed
      • Any
      • 两者的区别
  • Flow运行环境API

之前写了Flow的相关介绍,如果想回顾的参考 Flow(一)—— JavaScript静态类型检查器
,这里简单的介绍Flow的语法,了解Flow的意义是在第三方源码中可以看到Flow的使用情况,可以帮助我们更好的了解源码。

Flow类型推断

没有执行变量类型,但是可以根据代码的使用情况推断类型,就叫类型推断

// @flow
// 因为字符串不能进行乘法运算,所以也会报错
 function square (n) {
   return n * n
 }

 square('100')
image

不过虽然有类型推断,但是建议开发者每个都添加类型,这样有可读性。

Flow类型注解使用的地方

绝大多数flow都可以推断出变量类型,但是并不意味着我们不需要给每个变量添加类型注解。添加类型注解可以明确去限制类型,而且对我们之后理解这里的代码很有帮助,建议尽可能的去使用类型注解

  • 类型可以标注的地方
    • 函数参数
    • 变量
    • 函数返回值
// @flow
// 函数参数标注类型注解
function square (n: number) {
   return n * n
}

// 变量标注类型注解
let num: number = 100

// 函数返回值标注类型注解
function foo (): number {
   return 100
}
// 上面那种情况,如果没有返回值,默认返回undefind,上面也会报错
// 所以如果没有返回值,需要将返回类型标记为void
function foo1 (): void {
   
}

Flow Type Annotations

类型参考网址

原始类型

// @flow

 // 字符串
 const a: string = 'foobar'

 // 数字
 const b1: number = 100
 const b2: number = NaN
 const b3: number = Infinity // 无穷大

 // 布尔
 const c1: boolean = true
 const c2: boolean = false

 // null
 const d: null = null

 // undefined
 const e: void = undefined

 // symbol
 const f: symbol = Symbol()

数组类型

// @flow
// 写法一:Array后面要添加泛型参数,number指定全部由数字组成的数组,如果有其他类型就会报错
 const arr1: Array<number> = [1, 2, 3]
 const arr2: Array<mixed> = [1, true, "three",{a:'1',b:2}]
// 写法二:
 const arr3: number[] = [1, 2, 3]

除了这种数组写法,还有一种特殊的固定长度的数组,我们称为 —— 元组

元组 —— Tuple Types

  • 固定长度数组,如果改变长度会报错
  • 下标对应的元素必须是规定类型,设置新值得时候也必须匹配
  • 元组不匹配Array类型,因为数组类型长度不确定
  • 不能再元组上使用变异数组的方法,例如:copyWithinfillpoppushreverseshiftsortspliceunshift
// @flow
// 元组 —— 固定长度的数组
 // 下面的数组规定了两个元素,如果改变长度就会报错,而且下标对应的元素必须是规定的类型
 const arr4: [string, number] = ['foo', 100]
 arr4[2] = 1 // Cannot assign `1` to `arr3[2]` because  tuple type [1] only has 2 elements, so index 2 is out of bounds.
 const item0: string = arr4[0] // Works!
 const item1: number = arr4[0] // Cannot assign `arr3[0]` to `item1` because  string [1] is incompatible with  number [2]

对象类型

通用写法

确定一个对象中键值有哪些,并且每个是什么类型

// @flow
 const obj1: { foo: string, bar: number} = { foo: 'string', bar: 100}
 
// 如果访问了obj1中没有的属性,原来会返回undefined,现在直接当做类型报错
 obj1.baz // Cannot get `obj1.baz` because property `baz` (did you mean `bar`?) is missing in  object type [1]

添加可选属性

可选属性可以是undefined或者省略,但是不能是null

 // foo如果可有可无,那么在foo后面加一个问号
 // 可选属性可以是undefined或者省略,但是不能是null
 const obj2: { foo?: string, bar: number} = { bar: 100}
 obj2.foo = undefined // Works!
 obj2.foo = null // Cannot assign `null` to `obj2.foo` because  null [1] is incompatible with  string [2]

Map类

键的类型用方括号

 // 初始化为空,可以自己添加键值对,规定键是string类型,值也是string类型
 const obj3: { [string] : string } = {}

 obj3.key1 = 'value1'
 obj3.key2 = 100 // annot assign `100` to `obj3.key2` because  number [1] is incompatible with  string [2]

混合使用

Map类和普通可以混合使用

// @flow
var obj: {
  size: number,
  [id: number]: string
} = {
  size: 0
};

function add(id: number, name: string) {
  obj[id] = name;
  obj.size++;
}

函数类型

一般是指参数类型和返回值类型进行类型注解

函数参数

// @flow

// 参数输入确定类型
 function square (n: number) {
   return n * n
 }

可选函数参数

function func1 (num?: number) {
    const n = num ? num : 1
    console.log(n)
 }

 func1()  // 1  可以接受undefined,不能接受null
 func1(2) // 2
 func1(null) // Error!

Rest参数

// @flow
function method(...args: Array<number>) {
  // ...
}

method();        // Works.
method(1);       // Works.
method(1, 2);    // Works.
method(1, 2, 3); // Works.

函数返回

// 返回值确定类型
 // 有返回值
 function foo (): number {
   return 100
 }
 // 无返回值
 function foo1 (): void {
   
 }

// 回调函数参数和返回值类型 
 function func (callback: (string, number) => void) {
   callback('string', 100)
 }

 func(function (str, n) {
   // str => string
   // n => number
   // 无返回值
 })

特殊类型

字面量类型

与传统类型不同,这种字面量类型必须限制变量必须是某个值,一般不会单独使用,会配合 联合类型 去组合几个特性的值

// @flow
// 下面定义了n字面量,值只能是存放foo字符串,不能换成别的字符串和别的类型
const n: 'foo' = 'foo'
// 只能是下面三个字符串类型中的一种(下面的就是联合类型,也成或类型)
const type : 'success' | 'warning' | 'danger' = 'success'
// b变量既可以是string也可以是number,可以是字符串也可以是数字
const b: string | number = 'string' // 100 


// 也可以自己定义一个类型,StringOrNumber是一个类型的别名
type StringOrNumber = string | number
const test: StringOrNumber = 'string' // 100

maybe类型

有可能,在基本类型的基础上扩展了nullundefined的类型

// @flow
// 添加?可以使用null和undefined
const gender: ?number = null
const gender1: ?number = undefined
const gender2: ?number = 100

// 相等于下面的number或null或undefined
const gender: number | null | void = undefined

Mixed 与 Any

Mixed

Mixed可以接收任意类型的值,是所有类型的联合类型string | number | boolean | ...

// 参数是mixed类型
function passMixed (value: mixed) {
  console.log(value)
}

passMixed('string') // string
passMixed(100) // 100

Any

Mixed一样,可以接收任意类型的值

function passAny (value: any) {
    console.log(value)
}

passAny('string') // string

passAny(100) // 100

两者的区别

  • Mixed是一个强类型,如果有使用隐患的话就会报错,只能用typeof进行类型判断
  • Any是一个弱类型,如果有使用隐患,语法上不会报错。
  • Mixed是安全的(推荐使用),Any是不安全的,存在的意义是为了兼容老代码
// Mixed
// 如果没有明确这个变量是字符串还是数字,那么不能直接进行使用的,会报错
function passMixed (value: mixed) {
  console.log(value)
  value = value ** 2 // Cannot perform arithmetic operation because  mixed [1] is not a number.
}

// 如果想要 解决上面的问题,需要使用typeof进行类型判断
function passMixed (value: mixed) {
  if (typeof value === 'string') {
    value.substr(1)
  }
  if (typeof value === 'number') {
    value ** 2
  }
}

// Any
// 下面语法上是不会报错的, 运行阶段不确定
function passAny ( value: any) {
  value = value ** 2
}

Flow运行环境API

JavaScript需要运行在某个环境中,例如:浏览器环境或者node环境。
他们有本身自己的API,如浏览器中的DOMBOMnode中的path等,我们在flow中也会使用到这些对象。

那么这些有特殊的类型限制,例如:

document.getElementById() //里面参数传字符串,数字会报错
// 这是浏览器环境内置的API的一些限制
document.getElementById('app') //返回对应的类型是HTMLElement
// 如果没有找到对应元素,也返回null类型,那么接收的时候可以这么写
const element: HTMLElement | null = document.getElementById('app')

右键跳到定义可以看到,原生里面有定义

image

官网仓库给出了一些类型声明,开发的时候可以参考使用

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容