首頁 >web前端 >js教程 >javascript的擴充:如何使用flow靜態類型進行檢查報錯

javascript的擴充:如何使用flow靜態類型進行檢查報錯

不言
不言原創
2018-09-17 14:34:051848瀏覽

這篇文章帶給大家的內容是關於javascript的擴充:如何使用flow靜態類型進行檢查報錯,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

js 語言與 java、C 系列等語言有一點很大的不同,就是 js 語言是弱型別語言。 js 語言的這個特性可能會讓大家覺得 js 很自由,沒有強制性的約束,但當遇到大型專案的時候,js 的這個特性就會變得比較麻煩,因為這會導致團隊的程式碼很不可控。這個原因也是促使 TypeScript 誕生的一個很重要的原因。

但其實很多開發人員還是比較喜歡用 js 來開發項目,所以 facebook 開發出 flow 來幫助 js 語言擴展靜態類型檢查功能,規避上面提到的問題。

1. 程式碼範例

flow 規定,在需要做'flow 靜態類型檢查' 文件的開頭加上// @flow 這段註釋,讓工具識別這個檔案需要做靜態類型檢查,否則就會當作一般js 檔案對待,不做靜態型別檢查。

flow 靜態類型幾乎可以應用到所有的 js 對象,包括 es6 擴充的 class, module 等,也包含 jsx 語法。

以下是一些基礎的靜態型別舉例,更詳細的可以查看Type Annotations | Flow.

1.1 基本型別

與js 的基本資料型別類似,包括:

boolean: 對應js 的Boolean 類型

number: 對應js 的Number 類型

string: 對應js 的String 類型

null: 對應js 的null

void: 對應js 的undefined

正常的js 程式碼

let hello = 'hello'; // 声明一个变量

hello = 2 * 2; // 重新赋值

hello = []; // 重新赋值

加上flow 靜態型別檢查擴充的程式碼

// @flow

let hello: string = 'hello'; // 声明一个 string 类型的变量

hello = 2 * 2; // 报错

hello = []; // 报错

hello = 'hi'; // 重新赋值

1.2 函數

正常的js 代碼

function plus(a, b) {
  return a + b;
}

plus(); // NaN
plus(1); // NaN
plus(1, 2); // 3
plus('hello'); // 'helloundefined'
plus('hello', ' hi'); // 'hello hi'
plus({}, {}); // '[object Object][object Object]'

加上flow 靜態類型檢查擴展的代碼

// @flow

// 定义一个 '两个数字参数,返回值也是数字' 的函数
function plus(a: number, b: number): number {
  return a + b;
}

plus(); // 报错
plus(1); // 报错
plus('hello'); // 报错
plus('hello', ' hi'); // 报错
plus({}, {}); // 报错

plus(1, 2); // 3

1.3 可能(Maybe),可選(Optional),語義(Literal),混合( Mixed)

可能(Maybe)類型用一個? 在類型前面表示,包含類型本身、null、undefined

// @flow

let hello: ?string; // 声明一个数据类型可以是 string, null, undefined 的变量

hello = null; // 赋值
hello = undefined; // 重新赋值
hello = 'hello'; // 重新赋值
hello = 1; // 报错
hello = true; // 报错

可選(Optional)類型一般用於物件屬性或函數參數,在名稱後面加一個?,包含型別本身、undefined

// @flow

const obj: {hello? : string}; // 属性 hello 可以是 string, undefined

obj = {}; // 赋值
obj = {hello: undefined}; // 重新赋值
obj = {hello: 'hello'}; // 重新赋值
obj = {hello: null}; // 报错
obj = {hello: 1}; // 报错
obj = {hello: true}; // 报错

// 属性 param 可以是 number, undefined
function method(param?: number) { /* ... */ }

method(); // 正常
method(undefined); // 正常
method(1.12); // 正常
method(null); // 报错
method('hello'); // 报错

語意(Literal)型別一般用來宣告某個,某幾個特定的值(多個值以| 分隔)

// @flow

let hello: 'hello'; // 声明一个只能赋值 'hello' 的变量

hello = 'hello'; // 赋值
hello = 'hi'; // 报错
hello = 12; // 报错
hello = undefined; // 报错
hello = null; // 报错

function method(param: 1 | 'hi' | boolean): void { /* ... */ }

method(); // 报错,缺少参数
method(1); // ok
method(1.2); // 报错,类型不对
method('hi'); // ok
method('hello'); // 报错,类型不对
method(true); // ok
method(false); // ok

混合(Mixed)類型是指任意資料型別

// @flow

let hello: mixed; // 声明一个 mixed 类型的变量

hello = 'hello'; // 赋值
hello = 'hi'; // 重新赋值
hello = 12; // 重新赋值
hello = undefined; // 重新赋值
hello = null; // 重新赋值

1.4 複合型別

陣列

// @flow

let arr1: Array<boolean> = [true, false, true]; // 声明一个元素是 boolean 的数组
arr1 = [true, 1]; // 报错,1 不是 boolean 值
arr1 = ['']; // 报错,'' 不是 boolean 值

let arr2: Array<string> = ["A", "B", "C"]; // 声明一个元素是 string 的数组

let arr3: Array<mixed> = [1, true, "three"] // 声明一个元素是任意类型的数组
arr1 = [true, 1]; // 重新赋值 
arr1 = ['']; // 重新赋值

map

// @flow

// 声明一个 map 类型,其有一个名为 foo,类型 boolean 的子元素
let obj1: { foo: boolean } = { foo: true };
obj1 = {}; // 报错,缺少 foo 这个属性值
obj1 = {foo: 1}; // 报错,属性值 foo 的类型必须是 boolean
obj1 = {foo: false, bar: 'hello'}; // 重新赋值

// 声明一个 map 类型,其有名为 foo, bar, baz,类型 number, boolean, string 的子元素
let obj2: {
  foo: number,
  bar: boolean,
  baz: string,
} = {
  foo: 1,
  bar: true,
  baz: 'three',
};

更靜態類型可以查看Type Annotations | Flow.

2. 使用工具

安裝

# 全局安装
npm i -g flow-bin

# 本地安装
npm i -D flow-bin

使用

flow init                       # 初始化项目

flow check path/to/dir          # 检查这个目录下所有的文件
flow check path/to/js/file      # 检查指定文件

3. 配合babel 一起使用

因為flow 靜態類型只是對js 的擴展,並不是js 原生支援的,也不能直接運行,所以,一般flow 都是配合babel 一起使用的,這樣就可以在程式運行的時候進行靜態類型檢查,達到我們想要的效果。

3.1 babel-preset-flow

安裝 babel-preset-flow,讓 babel 在轉碼 js 檔案時就能辨識 flow 的語法。

npm i -D babel-preset-flow

.babelrc

{
  "presets": ["flow"]
}

原始檔(flow)

// @flow

// 定义一个 '两个数字参数,返回值也是数字' 的函数
function plus(a: number, b: number): number {
  return a + b;
}

plus(); // 报错
plus(1); // 报错
plus('hello'); // 报错
plus('hello', ' hi'); // 报错
plus({}, {}); // 报错

plus(1, 2); // 3

轉碼後的檔案

// 定义一个 '两个数字参数,返回值也是数字' 的函数
function plus(a, b) {
  return a + b;
}

plus(); // 报错
plus(1); // 报错
plus('hello'); // 报错
plus('hello', ' hi'); // 报错
plus({}, {}); // 报错

plus(1, 2); // 3

3.2 babel-plugin-flow-runtime

一般會在開發環境下,使用babel-plugin-flow-runtime 插件,這樣就可以在開發的時候,即時檢查資料類型,就像原生的運行flow 靜態類型檢查一樣。 (一般在產品環境不會使用這個功能,因為會額外消耗js 的效能)

npm i -D babel-plugin-flow-runtime flow-runtime

.babelrc

{
  "presets": ["flow"],
  "plugins": ["flow-runtime"]
}

來源檔(flow)

// @flow

// 定义一个 '两个数字参数,返回值也是数字' 的函数
function plus(a: number, b: number): number {
  return a + b;
}

plus(); // 报错
plus(1); // 报错
plus('hello'); // 报错
plus('hello', ' hi'); // 报错
plus({}, {}); // 报错

plus(1, 2); // 3

轉碼後的檔案

import t from 'flow-runtime';


// 定义一个 '两个数字参数,返回值也是数字' 的函数
function plus(a, b) {
  return a + b;
}

t.annotate(plus, t.function(t.param('a', t.number()), t.param('b', t.number()), t.return(t.number())));
plus(); // 报错
plus(1); // 报错
plus('hello'); // 报错
plus('hello', ' hi'); // 报错
plus({}, {}); // 报错

plus(1, 2); // 3

這個時候,js 檔案就會導入flow-runtime 模組,對plus 函數的參數a, b 和回傳值進行資料類型檢查,如果不符合資料定義,就會報錯。

以上是javascript的擴充:如何使用flow靜態類型進行檢查報錯的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn