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

当你将鼠标光标悬停在错误上时,你会看到一个提示,帮助你解决问题

要解决以错误顺序传递参数的问题,请显式地为函数参数分配类型
const showProduct = (name: string, price:number) => {
console.log(`The product ${name} costs $${price}.`);
};
Code language: JavaScript (javascript)
当你将错误类型的参数传递给 showProduct()
函数时,你会收到错误
const product = getProduct(1);
showProduct(product.price, product.name);
Code language: JavaScript (javascript)

总结
- JavaScript 是动态类型的,提供了灵活性,但也导致了许多问题。
- TypeScript 为 JavaScript 添加了一个可选的类型系统来解决这些问题。