在今天教程中,我们将了解一下为什么应该使用 TypeScript 而不是 JavaScript 以避免动态类型产生的问题。
为什么使用 TypeScript
使用 TypeScript 有两个主要原因:
-
TypeScript 添加了一个类型系统来帮助我们避免 JavaScript 中动态类型的许多问题。
-
TypeScript 实现了 JavaScript a.k.a ES Next 的未来功能,因此,我们现在可以使用它们。
本教程重点介绍第一个原因。
了解 JavaScript 中的动态类型
JavaScript 是动态类型, 与 Java 或 C# 等静态类型语言不同,值具有类型而不是变量。例如:
"Hello"
从值可以看出它的类型是string。此外,以下值是一个数字:
2020
请参见以下示例:
let box;
box = "hello";
box = 100;
box 变量的类型根据分配给它的值而变化。
要在运行时查找 box 变量的类型,请使用 typeof 运算符:
let box;
console.log(typeof(box)); // undefined
box = "Hello";
console.log(typeof(box)); // string
box = 100;
console.log(typeof(box)); // number
在这个例子中,第一条语句定义了变量而不赋值。它的类型是undefined(未定义的)。
然后,我们将“Hello”分配给 box 变量并显示其类型。box 变量的类型现在变为字符串。
最后,我们将 100 分配给 box 变量。这一次,box 变量的类型变为 number。
如您所见,一旦赋值,变量的类型就会改变。
而且我们不需要显式地告诉 JavaScript 类型。JavaScript 会自动从值中推断出类型。
动态类型提供了灵活性。但是,它们也会导致问题。
动态类型的问题
假设,我们有一个基于 id 返回产品对象的函数:
function getProduct(id){
return {
id: id,
name: `Awesome Gadget ${id}`,
price: 99.5
}
}
下面使用 getProduct() 函数检索 id 为 1 的产品并显示其数据:
const product = getProduct(1);
console.log(`The product ${product.Name} costs $${product.price}`);
输出:
The product undefined costs $99.5
这不是我们所期望的。
这段代码的问题是product对象没有 Name 属性。它具有第一个小写字母 n 的 name 属性。
但是,我们只能在运行脚本之前知道它。
在使用 JavaScript 时,引用对象上不存在的属性是一个常见问题。
以下示例定义了一个将产品信息输出到控制台的新函数:
const showProduct = (name, price) => {
console.log(`The product ${name} costs ${price}$.`);
};
以下使用 getProduct() 和 showProduct() 函数:
const product = getProduct(1);
showProduct(product.price, product.name);
输出:
The product 99.5 costs $Awesome Gadget 1
这次我们以错误的顺序将参数传递给 showProduct() 函数。这是我们在使用 JavaScript 时经常遇到的另一个常见问题。
这就是 TypeScript 发挥作用的原因。
Typescript 如何解决动态类型的问题
要解决引用对象上不存在的属性的问题,请执行以下步骤:
首先,使用接口定义product对象的“形状”。请注意,我们将在稍后的教程中了解该界面。
interface Product{
id: number,
name: string,
price: number
};
其次,明确使用 Product 类型作为 getProduct() 函数的返回类型:
function getProduct(id) : Product{
return {
id: id,
name: `Awesome Gadget ${id}`,
price: 99.5
}
}
当你引用一个不存在的属性时,代码编辑器会立即通知你:
const product = getProduct(1);
console.log(`The product ${product.Name} costs $${product.price}`);
代码编辑器在 Name 属性上突出显示以下错误:
当我们将鼠标光标悬停在错误上时,我们会看到有助于解决问题的提示:
为了解决以错误顺序传递参数的问题,我们将类型分配给函数参数:
const showProduct = (name: string, price:number) => {
console.log(`The product ${name} costs ${price}$.`);
};
当我们将错误类型的参数传递给 showProduct() 函数时,我们会收到一个错误:
const product = getProduct(1);
showProduct(product.price, product.name);
总结
-
JavaScript 是动态类型的。它提供了灵活性,但也产生了许多问题。
-
TypeScript 为 JavaScript 添加了一个可选的类型系统来解决这些问题。