编程与类型系统
上QQ阅读APP看书,第一时间看更新

1.3.2 弱类型与强类型

术语“强类型”和“弱类型”常被用来描述类型系统。类型系统的强度描述了该系统在实施类型约束时的严格程度。弱类型系统会隐式地尝试将值从其实际类型转换为使用该值时期望的类型。

思考这个问题:牛奶与白色相等吗?在强类型系统中,这二者不相等,因为牛奶是一种液体,将其与一种颜色进行比较没有意义。在弱类型系统中,我们可以说“牛奶的颜色是白色的,所以是的,牛奶等于白色”。在强类型系统中,通过让问题变得像下面这样更加明确,我们可以显式地将牛奶转换为颜色:牛奶的颜色等于白色吗?在弱类型系统中,则不需要这种改进。

JavaScript是弱类型的。通过在TypeScript中使用any类型并让JavaScript在运行时处理类型,可以看出这一点。JavaScript提供了两种相等运算符:==检查两个值是否相等,===检查值是否相等,以及值的类型是否相同,如程序清单1.15所示。因为JavaScript是弱类型的,所以"42" == 42这样的表达式的结果为true。这一点会让人感到意外,因为"42"是文本,而42是数字。

程序清单1.15 弱类型

隐式类型转换很方便,因为我们不必编写更多代码来显式地在类型之间进行转换,但是隐式类型转换也很危险,因为在许多情况中,我们不希望发生类型转换,但结果却让我们很意外。TypeScript是强类型的。在前面的例子中,如果我们将a声明为string,将b声明为number,那么TypeScript将不会编译上面的比较语句,如程序清单1.16所示。

程序清单1.16 强类型

现在,所有比较都将导致错误This condition will always return 'false' since the types 'string' and 'number' have no overlap。类型检查器发现我们在试图比较不同类型的值,所以拒绝编译代码。

虽然在短期内,弱类型系统更容易使用,因为它不要求程序员显式转换不同类型的值,但是弱类型系统不能提供强类型系统那样的保证。如果不能正确地实施类型,那么本章描述的大部分优点,以及本书剩余部分使用的技术将失去效用。

注意,虽然一个类型系统要么是动态的(在运行时进行类型检查),要么是静态的(在编译时进行类型检查),但是其强度在一个范围内:执行的隐式转换越多,该类型系统就越弱。大部分类型系统,包括强类型系统在内,会为其认为安全的转换提供有限的隐式转换。转换为boolean是一个常见的例子:在大多数语言中,即使anumber类型或者引用类型,if(a)也会编译。拓宽转换是另一个例子,第4章将会进行介绍。TypeScript只使用number类型表示数字值,但在其他某些语言中,假如我们需要一个16位的整数,但是传入了一个8位的整数,那么通常会自动把8位整数转换为16位整数,因为这种转换不存在数据损坏的风险(16位整数能够表示8位整数可以表示的任意值)。