返回

优化您的代码:TypeScript小状况之选且只选一个

前端

Union 类型

Union 类型允许您定义一个类型,该类型可以是多种其他类型的其中一种。例如,您可以定义一个 Engineer 对象的类型,其中 gender 字段可以是 "male""female"

interface Engineer {
  name: string;
  gender: "male" | "female";
}

使用 Union 类型时,您需要特别注意类型检查。例如,如果您有一个 Engineer 对象,并且您想检查其 gender 字段的值,您需要使用 in 运算符。

const engineer: Engineer = {
  name: "John Doe",
  gender: "male",
};

if (engineer.gender in ["male", "female"]) {
  console.log("Valid gender");
} else {
  console.log("Invalid gender");
}

交叉类型

交叉类型允许您定义一个类型,该类型是多个其他类型的组合。例如,您可以定义一个 Engineer 对象的类型,其中 gender 字段可以是 "male""female",并且 age 字段必须是一个数字。

interface Engineer {
  name: string;
  gender: "male" | "female";
}

interface Person {
  age: number;
}

type EngineerWithAge = Engineer & Person;

使用交叉类型时,您需要特别注意类型检查。例如,如果您有一个 EngineerWithAge 对象,并且您想检查其 gender 字段的值,您需要使用 in 运算符。

const engineerWithAge: EngineerWithAge = {
  name: "John Doe",
  gender: "male",
  age: 30,
};

if (engineerWithAge.gender in ["male", "female"]) {
  console.log("Valid gender");
} else {
  console.log("Invalid gender");
}

Discriminated Union 类型

Discriminated Union 类型是一种特殊的 Union 类型,它使用一个字段来区分不同的类型。例如,您可以定义一个 Engineer 对象的类型,其中 gender 字段可以是 "male""female",并且使用 type 字段来区分不同的工程师类型。

interface Engineer {
  name: string;
  gender: "male" | "female";
  type: "frontend" | "backend" | "fullstack";
}

使用 Discriminated Union 类型时,您可以使用 switch 语句来检查对象的 type 字段,并根据不同的类型执行不同的操作。

const engineer: Engineer = {
  name: "John Doe",
  gender: "male",
  type: "frontend",
};

switch (engineer.type) {
  case "frontend":
    console.log("Frontend engineer");
    break;
  case "backend":
    console.log("Backend engineer");
    break;
  case "fullstack":
    console.log("Fullstack engineer");
    break;
}

枚举

枚举是一种特殊的数据类型,它允许您定义一组具有固定值的常量。例如,您可以定义一个 Gender 枚举,其中包含 "male""female" 两个值。

enum Gender {
  Male = "male",
  Female = "female",
}

使用枚举时,您可以使用 switch 语句来检查对象的枚举值,并根据不同的值执行不同的操作。

const engineer: Engineer = {
  name: "John Doe",
  gender: Gender.Male,
  type: "frontend",
};

switch (engineer.gender) {
  case Gender.Male:
    console.log("Male engineer");
    break;
  case Gender.Female:
    console.log("Female engineer");
    break;
}

类型别名

类型别名允许您为一个类型定义一个新的名称。例如,您可以定义一个 Engineer 类型别名,该别名对应于 Engineer 接口。

type Engineer = {
  name: string;
  gender: "male" | "female";
};

使用类型别名时,您可以使用它来简化代码。例如,您可以使用 Engineer 类型别名来定义一个 engineers 数组。

const engineers: Engineer[] = [
  {
    name: "John Doe",
    gender: "male",
  },
  {
    name: "Jane Doe",
    gender: "female",
  },
];

比较

方法 优点 缺点
Union 类型 简单易用 容易出现类型错误
交叉类型 允许您组合多个类型 容易出现类型错误
Discriminated Union 类型 允许您区分不同的类型 需要额外的代码来处理类型区分
枚举 安全且易于使用 不能用于复杂的数据结构
类型别名 简化代码 不能用于定义新的类型

结论

在 TypeScript 中,当您需要定义一个对象的类型,此类型必须包含某n个字段中的其中一种时,您可以使用 Union 类型、交叉类型、Discriminated Union 类型、枚举或类型别名来实现。每种方法都有其优缺点,您需要根据具体情况选择合适的方法。