根據類型安全能夠將編程語言的類型系統分爲強類型或者弱類型。
根據類型檢查能夠將編程語言的類型系統分爲靜態類型和動態類型。javascript
因爲歷史因素,強類型和弱類型並無很是明確的定義。根據我的理解,能夠用下面這句話區分強弱類型。java
主要用以描述編程語言對於混入不一樣數據類型的值進行運算時的處理方式。強類型的語言遇到函數引數類型和實際調用類型不匹配的狀況常常會直接出錯或者編譯失敗;而弱類型的語言經常會實行隱式轉換,或者產生難以意料的結果。
在下例中,調用printNumber的時候傳入數字或者字符串都可,是一種弱類型語言。ajax
function printNumber(number){ console.log(number) } printNumber(100) //ok printNumber('100') //ok
在下例中,printNumber明確要求傳入int整型,若是調用時傳入字符串就會在編譯時出錯,所以是強類型語言。編程
class Main{ static void printNumber(int num) { System.out.printIn(num) } public static void main() { Main.printNumber(100) // ok Main.printNumber('100') // ok } }
靜態類型指的是變量的類型在編譯時老是已知的,也就是變量聲明完成後,不能改變其類型。數組
class Main{ public static void main() { int number = 100 number = 50 //ok number = '50' // error, 嘗試改變類型 } }
動態類型指的是變量的類型直到運行時才能肯定,也就是變量聲明完成後,可隨意更改其類型。安全
function main() { let num = 100 num = 50 // ok num = '50' // ok }
衆所周知,javascript是弱類型語言,也是一種動態類型語言。這是由語言設計時的侷限性決定的,當時,js只是用來完成簡單的功能,因此弱類型和動態類型能夠更爲方便。可是,如今js也能支持大型的應用開發,其類型的弊病就暴露出來。編程語言
setTimeout(() => { // 在這種狀況下,開發和簡單測試過程當中不會發現問題,只有運行一段時間後纔會爆出問題。 console.log(a) }, 3000000); let obj = { // 若是想要更改此屬性值,由於不知道有多少代碼中引入此屬性,因此不敢輕易更改。 name: 'zhangsan' } console.log(obj.name)
flow是一種JavaScript靜態類型檢查工具,經過類型註解的方式在項目編寫過程當中對類型加以限制,從而更早發現代碼問題,有利於項目的開發和維護。函數
類型註解:經過:的方式對變量的類型加以限制。工具
/** * @flow */ function sum(a: number, b: number) { return a + b } sum(1, 2) // ok sum('1', 2) //error // 因爲sum要求參數是數字,可是調用的時候傳入了字符串,因此在檢查的時候flow會報錯。
類型推斷:根據使用狀況自動推斷類型。測試
/** * @flow */ function square(a) { // 調用函數的時候傳入字符串,因此函數會自動推斷a參數爲字符串,由於字符串不容許相乘,所以檢查會報錯。 return a * a } square('a')
原始類型對應js中的原始類型。
const a: string = 'foo' const b: number = 1 // 也能夠賦值NaN(NaN是一種特殊的數字類型) const c: boolean = true // false const d: void = undefined const e: null = null const f: symbol = Symbol()
// 使用範型定義數組 const a: Array<number> = [1, 2, 3] const b: number[] = [1, 2, 3] // 使用元組定義數組類型:定義數組個數及每項類型。 const c: [string, number] = ['foo', 1]
// 相似對象字面量的方式定義對象中每一個屬性的類型 const obj: { name: string, age: number, // 可選 address?: string } = { name: 'zhangsan', age: 18 }
// 經過箭頭函數的方式定義函數類型 function ajax(callback: (string, number) => void) { callback('zhangsan', 18) }
// 指定一個字面量爲一個參數的類型, 一般字面量類型會和下面的聯合類型使用 const foo: 'foo' = 'foo'
// 指定類型爲多個字面量類型中的一個 const type: 'warning' | 'success' | 'error' = 'error' // 指定類型爲數組,數組能夠包含數字或者字符串 const arr: Array<number | string> = [1, '2']
// 經過type關鍵字定義一個類型,能夠認爲resultType是'warning' | 'success' | 'error'的別名 type resultType = 'warning' | 'success' | 'error' // 使用時能夠直接用resultType定義類型,方便複用 const type: resultType = 'error'
// 經過?定義可空類型,至關於 number | void let a: ?number = 1 a = undefined
// 經過mixed定義任意類型,能夠是基礎類型中的任意一個 let a: mixed = 1 a = 'foo' // any也能夠表示任意類型,表現上和mixed類似 let a: any = 1 a = 'foo'
mixed和any雖然表現相同,都表明任意類型,可是兩者是不同的,mixed雖然表示任意類型,可是它仍是強類型。
function anytest(s: any) { return s.substr(0, 1) } // 使用any時,能夠傳入任意類型的值,雖然數字可能不存在substr方法,可是檢查時不會報錯 anytest(1) function mixedtest(s: mixed){ // 使用mixed時,當這麼直接調用substr就會報錯,由於可能傳入number類型。 // return s.substr(0, 1) // 此時須要判斷參數類型 if(typeof s === 'string') { return s.substr(0, 1) } } mixedtest(1)
上面介紹了flow中經常使用的類型,其還包含一些不經常使用的類型,遇到後再補充。