根据类型安全能够将编程语言的类型系统分为强类型或者弱类型。
根据类型检查能够将编程语言的类型系统分为静态类型和动态类型。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中经常使用的类型,其还包含一些不经常使用的类型,遇到后再补充。