返回
超越“类型守卫”:TypeScript中的高效类型检查艺术
前端
2024-01-23 17:07:13
Words: 2831
TypeScript中的类型守卫是一种让代码更加可读和可维护的技术,它允许您更明确地指定变量的类型。类型守卫尤其有助于在某些情况下确保代码的正确性,例如,当您需要处理可能是多种类型的变量时,或者当您需要对不同类型的变量执行不同的操作时。
1. instanceof 类型守卫
instanceof 类型守卫用于检查一个变量是否属于某个类。使用 instanceof,您可以确保在访问或使用该变量之前,它具有正确的类型。
2. typeof 类型守卫
typeof 类型守卫用于检查一个变量的类型。typeof 运算符返回一个字符串,表示变量的类型。您可以使用 typeof 来确保变量具有正确的类型,然后再对其进行操作。
3. null检查和 undefined检查
null 和 undefined 检查是 TypeScript 中最基本的类型守卫。它们允许您检查变量是否为 null 或 undefined。这可以防止您在对变量进行操作之前访问或使用它。
4. 枚举类型守卫
枚举类型守卫用于检查一个变量是否属于某个枚举类型。枚举类型是一种特殊的类型,它包含一组命名常量。您可以使用枚举类型守卫来确保变量仅包含枚举中定义的常量。
5. 数组类型守卫
数组类型守卫用于检查一个变量是否属于某个数组类型。数组类型是一种特殊类型,它包含一组元素。您可以使用数组类型守卫来确保变量仅包含您期望的元素类型。
6. 函数类型守卫
函数类型守卫用于检查一个变量是否属于某个函数类型。函数类型是一种特殊类型,它了一个函数的参数和返回值类型。您可以使用函数类型守卫来确保变量仅包含您期望的函数类型。
7. 自定义类型守卫
自定义类型守卫允许您创建自己的类型守卫。这对于检查您自己的自定义类型非常有用。您可以使用自定义类型守卫来确保变量仅包含您期望的类型。
8. 泛型类型守卫
泛型类型守卫允许您创建适用于多种类型的类型守卫。这非常有用,因为您可以重用相同的类型守卫来检查不同的类型。
/* instanceof 类型守卫 */
class Person {
name: string;
}
class Employee extends Person {
salary: number;
}
function isEmployee(person: Person): person is Employee {
return person instanceof Employee;
}
const john = new Person();
const mary = new Employee();
if (isEmployee(john)) {
console.log(john.salary); // Error: Property 'salary' does not exist on type 'Person'.
}
if (isEmployee(mary)) {
console.log(mary.salary); // 10000
}
/* typeof 类型守卫 */
function isString(value: any): value is string {
return typeof value === "string";
}
const name = "John Doe";
const age = 30;
if (isString(name)) {
console.log(name.length); // 8
}
if (isString(age)) {
console.log(age.length); // Error: Property 'length' does not exist on type 'number'.
}
/* null 和 undefined 检查 */
function isNullOrUndefined(value: any): value is null | undefined {
return value === null || value === undefined;
}
const x = null;
const y = undefined;
if (isNullOrUndefined(x)) {
console.log("x is null or undefined"); // true
}
if (isNullOrUndefined(y)) {
console.log("y is null or undefined"); // true
}
/* 枚举类型守卫 */
enum Color {
Red,
Green,
Blue
}
function isColor(value: any): value is Color {
return Object.values(Color).includes(value);
}
const red = Color.Red;
const orange = "orange";
if (isColor(red)) {
console.log("red is a color"); // true
}
if (isColor(orange)) {
console.log("orange is a color"); // false
}
/* 数组类型守卫 */
function isNumberArray(value: any): value is number[] {
return Array.isArray(value) && value.every((item) => typeof item === "number");
}
const numbers = [1, 2, 3];
const strings = ["a", "b", "c"];
if (isNumberArray(numbers)) {
console.log("numbers is an array of numbers"); // true
}
if (isNumberArray(strings)) {
console.log("strings is an array of numbers"); // false
}
/* 函数类型守卫 */
function isAddFunction(value: any): value is (a: number, b: number) => number {
return typeof value === "function" && value.length === 2 && typeof value(1, 2) === "number";
}
const add = (a: number, b: number) => a + b;
const subtract = (a: number, b: number) => a - b;
if (isAddFunction(add)) {
console.log("add is an add function"); // true
}
if (isAddFunction(subtract)) {
console.log("subtract is an add function"); // false
}
/* 自定义类型守卫 */
interface Person {
name: string;
age: number;
}
function isPerson(value: any): value is Person {
return typeof value === "object" && "name" in value && "age" in value;
}
const john = {
name: "John Doe",
age: 30
};
const mary = {
name: "Mary Jane"
};
if (isPerson(john)) {
console.log(john.name); // John Doe
console.log(john.age); // 30
}
if (isPerson(mary)) {
console.log(mary.name); // Error: Property 'name' does not exist on type '{}'.
console.log(mary.age); // Error: Property 'age' does not exist on type '{}'.
}
/* 泛型类型守卫 */
function isArray