Bootstrap

15_TypeScript 对象 --[深入浅出 TypeScript 测试]

TypeScript 是一种静态类型的编程语言,它是 JavaScript 的超集,添加了可选的类型注解和其他特性,旨在提高代码的健壮性和开发效率。TypeScript 对象是键值对的集合,其中键通常是字符串(也可以是符号),值可以是任何类型的值,包括但不限于数字、字符串、布尔值、函数或其它对象。

在 TypeScript 中定义对象时,你可以使用接口(interface)或者类型别名(type alias)来描述对象的结构和属性的类型。下面是一些关于 TypeScript 对象的基础知识:

定义对象类型

1.使用接口

interface Person {
  name: string;
  age: number;
  isStudent?: boolean; // 可选属性
}

let person: Person = {
  name: "Alice",
  age: 25,
};

下面我将给出两个使用接口定义对象类型的示例。

示例 1: 简单的用户信息对象

在这个例子中,我们将定义一个表示用户信息的对象类型。这个对象将包含用户的姓名、年龄和电子邮件地址。我们还会添加一个可选属性phoneNumber,这意味着不是每个用户都必须提供电话号码。

// 定义接口 User
interface User {
  name: string;
  age: number;
  email: string;
  phoneNumber?: string; // 可选属性
}

// 创建符合 User 接口的对象实例
let user1: User = {
  name: "Alice",
  age: 28,
  email: "[email protected]"
};

let user2: User = {
  name: "Bob",
  age: 34,
  email: "[email protected]",
  phoneNumber: "555-6789" // 包含了可选属性
};

示例 2: 图书管理系统的图书对象

在第二个例子中,我们将创建一个用于图书管理系统的接口。每个图书对象应该有标题、作者、出版年份,并且可能有一个关于该书是否已借出的布尔属性。

// 定义接口 Book
interface Book {
  title: string;
  author: string;
  publishedYear: number;
  isBorrowed?: boolean; // 可选属性,默认是 false
}

// 创建符合 Book 接口的对象实例
let book1: Book = {
  title: "The Great Gatsby",
  author: "F. Scott Fitzgerald",
  publishedYear: 1925
};

let book2: Book = {
  title: "1984",
  author: "George Orwell",
  publishedYear: 1949,
  isBorrowed: true // 已借出状态
};

这两个示例展示了如何使用接口来定义对象的结构,以及如何根据这些接口创建具体的对象实例。通过这种方式,我们可以确保对象具有特定的属性,并且可以为某些属性设置默认值或使其成为可选项。

2.使用类型别名

// 定义一个类型别名 Address,用于描述地址对象的结构。
// 每个地址对象都应该有以下三个属性:
// - street: 街道地址(例如:门牌号和街道名称)
// - city: 城市名称
// - zipCode: 邮政编码
type Address = {
  street: string;   // 必填属性:街道信息
  city: string;     // 必填属性:城市信息
  zipCode: string;  // 必填属性:邮政编码
};

// 创建一个符合 Address 类型的对象实例,并赋值给变量 address。
// 这个对象代表一个具体的地址,包含了街道、城市和邮政编码的信息。
let address: Address = {
  street: "123 Main St", // 设置街道信息
  city: "Wonder City",   // 设置城市信息
  zipCode: "90210"       // 设置邮政编码
};

下面是两个使用类型别名(type)来定义对象类型的示例。类型别名提供了一种定义复杂类型的简便方式,并且可以用来创建联合类型、元组或对象类型。

示例 1: 定义用户信息对象类型

在这个例子中,我们将使用类型别名来定义一个表示用户信息的对象类型。这个对象将包含用户的姓名、年龄和电子邮件地址。我们还会添加一个可选属性phoneNumber,这意味着不是每个用户都必须提供电话号码。

// 使用类型别名定义 User 对象的结构
type User = {
  name: string;        // 用户的名字
  age: number;         // 用户的年龄
  email: string;       // 用户的电子邮件地址
  phoneNumber?: string; // 可选属性:用户的电话号码
};

// 创建符合 User 类型的对象实例
let user1: User = {
  name: "Alice",
  age: 28,
  email: "[email protected]"
};

let user2: User = {
  name: "Bob",
  age: 34,
  email: "[email protected]",
  phoneNumber: "555-6789" // 包含了可选属性
};

示例 2: 定义图书管理系统的图书对象类型

在第二个例子中,我们将创建一个用于图书管理系统的类型别名。每个图书对象应该有标题、作者、出版年份,并且可能有一个关于该书是否已借出的布尔属性。

// 使用类型别名定义 Book 对象的结构
type Book = {
  title: string;            // 图书的标题
  author: string;           // 图书的作者
  publishedYear: number;    // 图书的出版年份
  isBorrowed?: boolean;     // 可选属性:图书是否被借出,默认是 false
};

// 创建符合 Book 类型的对象实例
let book1: Book = {
  title: "The Great Gatsby",
  author: "F. Scott Fitzgerald",
  publishedYear: 1925
};

let book2: Book = {
  title: "1984",
  author: "George Orwell",
  publishedYear: 1949,
  isBorrowed: true // 已借出状态
};

这两个示例展示了如何使用类型别名来定义对象的结构,并确保对象具有特定的属性。类型别名可以非常灵活地用于描述各种复杂的类型,包括但不限于对象类型。如果你想要更进一步,你还可以使用类型别名来创建更复杂的类型,例如带有函数签名的对象类型等。

访问对象属性

  • 使用点符号访问:object.property
  • 使用方括号访问:object['property'],这允许使用变量作为属性名。

下面是两个示例,展示了如何在 TypeScript 中定义对象类型,并访问这些对象的属性。每个示例将包含对象类型的定义以及如何创建对象实例和访问其属性。

示例 1: 定义用户信息对象并访问属性

在这个例子中,我们将使用类型别名来定义一个表示用户信息的对象类型,并演示如何创建该类型的对象实例以及如何访问其属性。

// 使用类型别名定义 User 对象的结构
type User = {
  name: string;        // 用户的名字
  age: number;         // 用户的年龄
  email: string;       // 用户的电子邮件地址
  phoneNumber?: string; // 可选属性:用户的电话号码
};

// 创建符合 User 类型的对象实例
let user: User = {
  name: "Alice",
  age: 28,
  email: "[email protected]"
};

// 访问对象属性的方法:
// 1. 使用点符号访问
console.log(user.name); // 输出: Alice
console.log(user.age);  // 输出: 28

// 2. 使用方括号访问(允许动态属性名)
console.log(user['email']); // 输出: [email protected]

// 如果属性是可选的,在访问之前最好检查一下它是否存在
if (user.phoneNumber) {
  console.log(user.phoneNumber);
} else {
  console.log("Phone number not provided.");
}

示例 2: 定义图书信息对象并访问属性

这个例子展示了一个图书管理系统的图书对象,包括如何定义图书对象类型、创建图书对象实例及访问其属性。

// 使用类型别名定义 Book 对象的结构
type Book = {
  title: string;            // 图书的标题
  author: string;           // 图书的作者
  publishedYear: number;    // 图书的出版年份
  isBorrowed?: boolean;     // 可选属性:图书是否被借出,默认是 false
};

// 创建符合 Book 类型的对象实例
let book: Book = {
  title: "The Great Gatsby",
  author: "F. Scott Fitzgerald",
  publishedYear: 1925,
  isBorrowed: true
};

// 访问对象属性的方法:
// 1. 使用点符号访问
console.log(book.title);      // 输出: The Great Gatsby
console.log(book.author);     // 输出: F. Scott Fitzgerald

// 2. 使用方括号访问
console.log(book['publishedYear']); // 输出: 1925

// 对于布尔值属性,可以直接用于条件判断
if (book.isBorrowed) {
  console.log(`${book.title} is currently borrowed.`);
} else {
  console.log(`${book.title} is available.`);
}

在这两个示例中,我们使用了两种方法来访问对象属性:点符号和方括号。点符号适合直接知道属性名的情况下使用,而方括号则适用于当属性名存储在变量中或属性名包含特殊字符时。此外,对于可选属性,在尝试访问它们之前进行存在性检查是一个良好的实践,以避免运行时错误。

添加方法

对象不仅可以包含数据属性,还可以包含方法(即函数属性):

// 定义一个接口 Animal,用于描述所有动物对象应该具有的公共属性和方法。
// 每个实现了 Animal 接口的对象都应该有一个 'name' 属性和一个 'speak' 方法。
interface Animal {
  name: string;    // 必须包含一个字符串类型的 'name' 属性,用来表示动物的名字。
  speak(): void;   // 必须实现一个名为 'speak' 的方法,它不接受参数且不返回任何值(void)。
                   // 这个方法应该定义动物如何发声。
}

// 创建一个符合 Animal 接口的对象实例,并赋值给变量 dog。
// 这个对象代表一只名叫 "Buddy" 的狗,并实现了 'speak' 方法来模拟它的叫声。
let dog: Animal = {
  name: "Buddy",   // 设置狗的名字为 "Buddy"。
  speak: function() {
    // 当调用 'speak' 方法时,打印一条消息到控制台,表明这只狗在叫。
    // 使用模板字符串 `${this.name}` 来插入当前对象的 'name' 属性值。
    console.log(`${this.name} says woof!`);
  }
};

// 调用 'speak' 方法,这将输出: "Buddy says woof!"
dog.speak();

在 TypeScript 中,我们可以在定义对象类型时添加方法。这可以通过接口或类型别名来完成。下面我将给出两个示例,展示如何向对象中添加方法。

示例 1: 用户信息对象与打招呼方法

在这个例子中,我们将创建一个表示用户信息的对象类型,并为其添加一个greet方法,该方法允许用户进行自我介绍。

// 使用接口定义 User 对象的结构并添加方法
interface User {
  name: string;        // 用户的名字
  age: number;         // 用户的年龄
  email: string;       // 用户的电子邮件地址
  greet(): string;     // 方法:返回用户的问候语
}

// 创建符合 User 接口的对象实例,并实现 greet 方法
let user: User = {
  name: "Alice",
  age: 28,
  email: "[email protected]",
  greet: function(): string {
    return `Hello, my name is ${this.name}. Nice to meet you!`;
  }
};

// 调用对象的方法
console.log(user.greet()); // 输出: Hello, my name is Alice. Nice to meet you!

示例 2: 图书信息对象与借阅状态方法

这个例子展示了一个图书管理系统的图书对象,并为它添加了borrowBookreturnBook方法来改变图书的借阅状态。

// 使用类型别名定义 Book 对象的结构并添加方法
type Book = {
  title: string;            // 图书的标题
  author: string;           // 图书的作者
  publishedYear: number;    // 图书的出版年份
  isBorrowed: boolean;      // 图书是否被借出,默认是 false
  borrowBook(): void;       // 方法:设置图书为已借出状态
  returnBook(): void;       // 方法:设置图书为可借阅状态
};

// 创建符合 Book 类型的对象实例,并实现方法
let book: Book = {
  title: "The Great Gatsby",
  author: "F. Scott Fitzgerald",
  publishedYear: 1925,
  isBorrowed: false,
  borrowBook: function() {
    if (!this.isBorrowed) {
      this.isBorrowed = true;
      console.log(`${this.title} has been borrowed.`);
    } else {
      console.log(`${this.title} is already borrowed.`);
    }
  },
  returnBook: function() {
    if (this.isBorrowed) {
      this.isBorrowed = false;
      console.log(`${this.title} has been returned.`);
    } else {
      console.log(`${this.title} was not borrowed.`);
    }
  }
};

// 调用对象的方法
book.borrowBook(); // 输出: The Great Gatsby has been borrowed.
book.borrowBook(); // 输出: The Great Gatsby is already borrowed.
book.returnBook(); // 输出: The Great Gatsby has been returned.
book.returnBook(); // 输出: The Great Gatsby was not borrowed.

在这两个示例中,我们展示了如何通过定义对象类型来添加方法,以及如何创建这些类型的对象实例并实现那些方法。方法可以执行各种逻辑操作,如修改对象的状态、计算值或与其他对象交互。当调用这些方法时,它们可以用来改变对象内部的数据或产生副作用(例如打印消息到控制台)。

构造对象

除了直接创建对象字面量外,你还可以使用构造函数或类来创建对象:

// 定义一个 Vehicle 类,它有两个公共属性:make(制造商)和 model(型号)。
class Vehicle {
  // 构造函数接收两个参数,并将它们赋值给类的公共属性。
  constructor(public make: string, public model: string) {}
}

// 创建一个新的 Vehicle 类的实例,代表一辆具体的汽车。
// 这里我们创建了一辆丰田卡罗拉 (Toyota Corolla)。
let car = new Vehicle("Toyota", "Corolla"); // 实例化 Vehicle 类,传入制造商和型号作为参数。

在 TypeScript 中,构造对象可以通过直接创建对象字面量、使用类的构造函数或工厂函数等方式来完成。下面是两个使用不同方法构造对象的示例。

示例 1: 使用类构造对象

在这个例子中,我们将定义一个 Person 类,并使用构造函数来创建 Person 对象实例。每个 Person 对象将包含姓名和年龄属性,以及一个打招呼的方法。

// 定义 Person 类,它有两个公共属性:name(名字)和 age(年龄),并且有一个 greet 方法。
class Person {
  constructor(public name: string, public age: number) {}

  // 定义一个方法 greet,用于输出一条欢迎信息。
  greet(): void {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  }
}

// 创建一个新的 Person 类的实例,代表一个具体的人。
let alice = new Person("Alice", 30);

// 调用实例的方法
alice.greet(); // 输出: Hello, my name is Alice and I am 30 years old.

示例 2: 使用工厂函数构造对象

这个例子展示了如何使用工厂函数来创建对象。工厂函数是一种设计模式,它提供了一种创建对象的方式,而不需要通过类的构造函数。

// 工厂函数 createBook 接受三个参数并返回一个符合 Book 接口的对象。
function createBook(title: string, author: string, publishedYear: number): { title: string; author: string; publishedYear: number; isAvailable: boolean } {
  return {
    title,
    author,
    publishedYear,
    isAvailable: true, // 默认书籍是可用的
  };
}

// 使用工厂函数创建新的书籍对象实例。
let book = createBook("The Great Gatsby", "F. Scott Fitzgerald", 1925);

// 访问对象的属性
console.log(book.title); // 输出: The Great Gatsby
console.log(book.author); // 输出: F. Scott Fitzgerald

// 修改对象的属性
book.isAvailable = false;

// 打印书籍是否可借阅的状态
console.log(`${book.title} is ${book.isAvailable ? 'available' : 'not available'} to borrow.`);

在这两个示例中,我们展示了两种不同的方式来构造对象:一种是使用类的构造函数,另一种是使用工厂函数。每种方法都有其适用场景,选择哪种方法取决于你的需求和个人偏好。使用类可以更方便地添加方法和实现继承等面向对象编程特性;而工厂函数则提供了更大的灵活性,尤其是在需要根据不同的条件创建不同类型的对象时。

;