在 TypeScript 中,类型系统是确保代码质量的关键特性之一。通过类型注解和类型推断,开发者可以构建出既灵活又安全的应用。本文对 TypeScript 类型系统的深入探讨,是系列文章的第二篇。
1. 其它需要手动显式指定类型的情况
-
变量声明时初始化延后:当变量在声明时不立即初始化时,TypeScript可能无法推断其类型。例如:
let foundWord: boolean; for (let i = 0; i < words.length; i++) { if (words[i] === 'green') { foundWord = true; // 显式指定类型为boolean } } -
变量类型无法正确推断:当变量的类型不能被TypeScript正确推断时,需要显式指定类型。例如:
let numbers = [-10, -1, 12]; let numberAboveZero: boolean; // 显式指定类型为boolean for (let i = 0; i < numbers.length; i++) { if (numbers[i] > 0) { numberAboveZero = true; } }
2. 函数返回值类型约束
为函数的返回值指定类型可以防止错误,提高代码的健壮性。例如:
const add = (a: number, b: number): number => {
return a + b;
};
3. 函数返回值为never和void
never用于表示函数不会返回任何值,通常用于错误处理;void表示函数没有返回值。例如:
const logger = (message: string): void => {
console.log(message);
};
const throwError = (message: string): never => {
throw new Error(message);
};
4. 带类型约束的形参解构
在函数参数中使用解构赋值时,可以显式指定解构后的变量类型。例如:
const logWeather = ({ date, weather }: { date: Date, weather: string }): void => {
console.log(date);
console.log(weather);
};
5. 数组类型约束
当需要确保数组中元素的类型一致性时,可以显式指定数组的类型。例如:
let numbers: number[] = [-10, -1, 12]; // 显式指定数组元素类型为number
数组类型约束的好处
- 防止向数组中添加不兼容的值。
- 在使用
map、forEach、reduce等数组函数时获得类型帮助。 - 保持数组的灵活性,允许数组包含不同类型的元素。
6. 元组(Tuple)
元组用于将不同类型的数据成组,并且考虑其顺序。例如:
const pepsi: [string, boolean, number] = ['brown', true, 40];
但通常不推荐使用元组,因为接口(interface)可以实现相同的功能,并且具有更强的语义。
7. 使用type来简化代码
通过使用type别名,我们可以简化代码并提高可读性(因为有的时候有些类型约束真的很长,所以重复写的话可读性很差)。例如:
type Drink = [string, boolean, number];
const pepsi: Drink = ['brown', true, 40];
const sprite: Drink = ['clear', true, 40];
const tea: Drink = ['brown', false, 0];
8. 接口(Interfaces)
接口在TypeScript中用于定义对象的结构,是实现代码复用的强大工具。接口可以定义属性和方法,例如:
interface Vehicle {
name: string;
year: Date;
broken: boolean;
summary(): string;
}
const oldCivic = {
name: 'civic',
year: new Date(),
broken: true,
summary: function(): string {
return `Name: ${this.name}`;
}
};
function printVehicle(vehicle: Vehicle): void {
console.log(vehicle.summary());
}
// 调用函数以打印oldCivic的摘要信息
printVehicle(oldCivic);
在上述代码中,printVehicle函数接受一个实现了Vehicle接口的对象作为参数。传入的对象只需要具有接口要求的所有属性即可通过类型检测。如果对象中的属性多于接口定义的属性,则不会报错,这提供了一定的灵活性。
第 2 篇内容提纲
1. 手动显式指定类型的情况
- 变量声明后初始化:变量声明时不立即赋值,需显式指定类型。
- 类型推断失败:变量类型无法被TypeScript正确推断,需明确类型。
2. 函数返回值类型约束
- 防止错误:通过指定返回值类型,提高代码健壮性。
3. 特殊返回值类型never和void
never:用于错误处理,表示函数不返回任何值。void:表示函数没有返回值。
4. 带类型约束的形参解构
- 函数参数解构:在函数参数中使用解构赋值时,显式指定类型。
5. 数组类型约束
- 元素类型一致性:确保数组中元素类型统一。
- 好处:
- 防止添加不兼容值。
- 使用数组函数时获得类型帮助。
- 保持数组灵活性。
6. 元组(Tuple)
- 数据类型和顺序:用于组合不同类型的数据并考虑顺序。
- 不推荐使用原因:接口可实现相同功能,语义更强。
7. 使用type简化代码
- 类型别名:简化复杂类型约束,提高代码可读性。
8. 接口(Interfaces)
- 定义对象结构:用于实现代码复用。
- 属性和方法定义:接口定义对象应具备的属性和方法。
- 灵活性:传入对象只需满足接口要求的属性,多于定义的属性不会报错。