文章目录
- 面向对象
- TypeScript 接口详解
- 接口的基本定义
- 示例
- 联合类型和接口
- 示例
- 接口和数组
- 示例
- 接口继承
- 单接口继承
- 多接口继承
- TypeScript 类详解
- 类的基本定义
- 创建类
- 创建实例化对象
- 类的继承
- 示例
- 方法重写
- 示例
- static 关键字
- 示例
- instanceof 运算符
- 示例
- 访问控制修饰符
- 示例
- 类与接口
- 示例
- TypeScript 对象详解
- 对象的基本定义
- 访问对象的值
- TypeScript 类型模板
- 传递对象作为函数参数
- 示例
- TypeScript 泛型详解
- 泛型的优势
- 泛型标识符
- 泛型函数
- 泛型接口
- 泛型类
- 泛型约束
- 泛型与默认值
- 泛型函数例子
- 代码说明:
- 输出示例:
- 学习总结
面向对象
TypeScript 接口详解
接口是 TypeScript 中用于定义对象结构的工具,它提供了一组方法和属性的抽象声明,确保实现这些接口的类或对象遵循相应的结构。
接口的基本定义
TypeScript 接口的基本定义如下:
typescript">interface InterfaceName {
}
示例
下面是一个关于车辆的接口示例:
typescript">interface IVehicle {
brand: string;
model: string;
year: number;
start: () => string;
}
const car: IVehicle = {
brand: "Toyota",
model: "Camry",
year: 2020,
start: (): string => { return "Engine started!"; }
};
console.log("Car Details:");
console.log(`Brand: ${car.brand}`);
console.log(`Model: ${car.model}`);
console.log(`Year: ${car.year}`);
console.log(car.start());
输出结果:
Car Details:
Brand: Toyota
Model: Camry
Year: 2020
Engine started!
联合类型和接口
接口支持联合类型,允许某个属性接受多种类型的值。
示例
typescript">interface RequestOptions {
url: string;
method: string;
headers?: { [key: string]: string };
body?: string | object | (() => string);
}
// 使用字符串作为 body
let request: RequestOptions = { url: "https://api.example.com", method: "GET" ,body:"this is body"};
console.log(request.body);
// 使用对象作为 body
request = { url: "https://api.example.com", method: "POST", body: { name: "John" } };
console.log(request.body);
// 使用函数作为 body
request = { url: "https://api.example.com", method: "PUT", body: () => "Update data" };
console.log((request.body as () => string)());
输出结果:
undefined
{ name: 'John' }
Update data
接口和数组
接口中可以定义数组的索引和元素类型。
示例
typescript">interface StringList {
[index: number]: string;
}
// 正确示例
const fruits: StringList = ["Apple", "Banana", "Cherry"];
console.log(fruits);
// 错误示例:元素类型不匹配
// const fruits: StringList = ["Apple", 1, "Cherry"]; // 会报错
接口继承
接口可以通过其他接口进行扩展,TypeScript 允许单接口或多接口的继承。
单接口继承
typescript">interface Employee {
id: number;
name: string;
}
interface Manager extends Employee {
department: string;
}
const manager: Manager = {
id: 1,
name: "Alice",
department: "Sales"
};
console.log(`Manager: ${manager.name}, Department: ${manager.department}`);
输出结果:
Manager: Alice, Department: Sales
多接口继承
typescript">interface IAddress {
street: string;
city: string;
}
interface IContact {
email: string;
phone: string;
}
interface IUser extends IAddress, IContact {
username: string;
}
const user: IUser = {
username: "john_doe",
street: "123 Main St",
city: "New York",
email: "john@example.com",
phone: "123-456-7890"
};
console.log(`User: ${user.username}, Email: ${user.email}`);
输出结果:
User: john_doe, Email: john@example.com
TypeScript 类详解
TypeScript 是一种面向对象的 JavaScript,它允许我们使用类、接口等特性来组织代码。类定义了对象的共同属性和方法。
类的基本定义
TypeScript 中类的定义格式如下:
typescript">class ClassName {
// 类的属性和方法
}
类的定义包括以下几个部分:
- 字段:类中声明的变量,表示对象的数据。
- 构造函数:在实例化类时调用,用于初始化对象。
- 方法:类中定义的功能,可以被对象调用。
创建类
以下示例展示了一个 Book
类,包含字段 title
和 author
,并通过构造函数初始化这些字段。
typescript">class Book {
title: string;
author: string;
constructor(title: string, author: string) {
this.title = title;
this.author = author;
}
displayInfo(): void {
console.log(`书名: ${this.title}, 作者: ${this.author}`);
}
}
创建实例化对象
使用 new
关键字来实例化类的对象:
typescript">const myBook = new Book("1984", "George Orwell");
// 访问字段
console.log(`书名: ${myBook.title}`);
// 调用方法
myBook.displayInfo();
输出结果:
书名: 1984
书名: 1984, 作者: George Orwell
类的继承
TypeScript 支持类的继承,子类可以从父类继承属性和方法。
示例
typescript">class Vehicle {
brand: string;
constructor(brand: string) {
this.brand = brand;
}
displayBrand(): void {
console.log(`品牌: ${this.brand}`);
}
}
class Car extends Vehicle {
model: string;
constructor(brand: string, model: string) {
super(brand); // 调用父类构造函数
this.model = model;
}
displayInfo(): void {
this.displayBrand();
console.log(`车型: ${this.model}`);
}
}
const myCar = new Car("Toyota", "Corolla");
myCar.displayInfo();
输出结果:
品牌: Toyota
车型: Corolla
方法重写
子类可以重写父类的方法,以实现特定功能。
示例
typescript">class Animal {
sound(): void {
console.log("动物发出声音");
}
}
class Dog extends Animal {
sound(): void {
console.log("汪汪!");
}
}
const myDog = new Dog();
myDog.sound(); // 输出:汪汪!
static 关键字
使用 static
关键字定义静态属性和方法,这些成员可以直接通过类名调用。
示例
typescript">class Counter {
static count: number = 0;
static increment(): void {
this.count++;
console.log(`计数器: ${this.count}`);
}
}
Counter.increment(); // 输出:计数器: 1
Counter.increment(); // 输出:计数器: 2
instanceof 运算符
instanceof
用于检查一个对象是否为某个类的实例。
示例
typescript">class Person {}
const john = new Person();
const isPerson = john instanceof Person;
console.log(`john 是 Person 的实例吗? ${isPerson}`); // 输出:true
访问控制修饰符
TypeScript 提供了三种访问修饰符:
- public(默认):可以在任何地方访问。
- protected:只能在类自身及其子类中访问。
- private:只能在定义该成员的类中访问。
示例
typescript">class User {
public name: string;
private password: string;
constructor(name: string, password: string) {
this.name = name;
this.password = password;
}
}
const user = new User("Alice", "123456");
console.log(user.name); // 可访问
// console.log(user.password); // 编译错误:属性 'password' 是私有的
类与接口
类可以实现接口,使用 implements
关键字。
示例
typescript">interface IAccount {
accountNumber: number;
balance: number;
deposit(amount: number): void;
}
class BankAccount implements IAccount {
accountNumber: number;
balance: number;
constructor(accountNumber: number, balance: number) {
this.accountNumber = accountNumber;
this.balance = balance;
}
deposit(amount: number): void {
this.balance += amount;
console.log(`存款: ${amount}, 余额: ${this.balance}`);
}
}
const account = new BankAccount(123456, 1000);
account.deposit(500); // 输出:存款: 500, 余额: 1500
TypeScript 对象详解
在 TypeScript 中,对象是键值对的集合,可以包含不同类型的数据,包括标量、函数和数组。
对象的基本定义
以下是一个包含多种类型值的对象示例:
typescript">const userProfile = {
username: "john_doe", // 标量
age: 30,
greet: function() { // 函数
console.log(`Hello, my name is ${this.username}`);
},
hobbies: ["reading", "gaming"] // 数组
};
// 调用函数
userProfile.greet(); // 输出: Hello, my name is john_doe
访问对象的值
可以使用点操作符访问对象的属性:
typescript">const product = {
name: "Laptop",
price: 999.99
};
// 访问对象的值
console.log(`Product: ${product.name}`); // 输出: Product: Laptop
console.log(`Price: $${product.price}`); // 输出: Price: $999.99
TypeScript 类型模板
在 TypeScript 中,定义对象类型可以帮助确保结构的一致性。例如,创建一个包含详细信息的对象:
typescript">const book: { title: string; author: string; pages: number; summarize: () => void } = {
title: "The Great Gatsby",
author: "F. Scott Fitzgerald",
pages: 218,
summarize: function() {
console.log(`${this.title} by ${this.author} has ${this.pages} pages.`);
}
};
// 调用方法
book.summarize(); // 输出: The Great Gatsby by F. Scott Fitzgerald has 218 pages.
传递对象作为函数参数
可以将对象作为参数传递给函数,并在函数中使用类型定义来确保对象的结构正确。
示例
typescript">const car = {
make: "Tesla",
model: "Model S",
year: 2021
};
const displayCarInfo = function(carInfo: { make: string; model: string; year: number }) {
console.log(`Car Make: ${carInfo.make}`);
console.log(`Car Model: ${carInfo.model}`);
console.log(`Car Year: ${carInfo.year}`);
};
displayCarInfo(car);
// 输出:
// Car Make: Tesla
// Car Model: Model S
// Car Year: 2021
TypeScript 泛型详解
泛型(Generics)是一种强大的编程特性,允许在定义函数、类和接口时使用占位符表示类型,使得代码更加灵活和可重用。泛型能够处理多种数据类型,而不会丢失类型安全。
泛型的优势
- 代码重用:可以编写与具体类型无关的通用代码,提高代码的复用性。
- 类型安全:在编译阶段进行类型检查,避免运行时的类型错误。
- 抽象性:支持编写更抽象和通用的代码,适应不同的数据类型和结构。
泛型标识符
在定义泛型时,常用的标识符有:
T
:表示 “Type”,最常见的泛型类型参数。K
,V
:通常用于表示键(Key)和值(Value)的泛型类型参数。
typescript">function echo<T>(arg: T): T {
return arg;
}
泛型函数
使用泛型可以创建处理不同类型的函数。例如:
typescript">function wrapInArray<T>(item: T): T[] {
return [item];
}
// 使用泛型函数
const numberArray = wrapInArray(123);
console.log(numberArray); // 输出: [123]
const stringArray = wrapInArray("Hello");
console.log(stringArray); // 输出: ["Hello"]
在这个例子中,wrapInArray
是一个泛型函数,接受一个参数并返回包含该参数的数组。
泛型接口
可以定义泛型接口,使其成员能够使用任意类型:
typescript">interface Pair<K, V> {
key: K;
value: V;
}
// 使用泛型接口
const numberStringPair: Pair<number, string> = { key: 1, value: "One" };
console.log(numberStringPair); // 输出: { key: 1, value: 'One' }
在此例中,定义了一个泛型接口 Pair
,然后创建了一个包含数字和字符串的对象。
泛型类
泛型也可以应用于类的属性和方法:
typescript">class Container<T> {
private items: T[] = [];
addItem(item: T): void {
this.items.push(item);
}
getItems(): T[] {
return this.items;
}
}
// 使用泛型类
const stringContainer = new Container<string>();
stringContainer.addItem("Hello");
console.log(stringContainer.getItems()); // 输出: ["Hello"]
在这个例子中,Container
是一个泛型类,能够存储任意类型的数组。
泛型约束
如果需要限制泛型的类型,可以使用泛型约束:
typescript">interface HasLength {
length: number;
}
function logLength<T extends HasLength>(item: T): void {
console.log(item.length);
}
// 正确使用
logLength("Hello"); // 输出: 5
// 错误使用,数字没有 length 属性
// logLength(123); // 编译错误
这里,logLength
函数接受一个参数,但有一个约束,要求传入的类型必须实现 HasLength
接口。
泛型与默认值
可以为泛型设置默认值,使得在不指定类型时使用默认类型:
typescript">function createPair<K = string, V = number>(key: K, value: V): Pair<K, V> {
return { key, value };
}
// 使用带默认值的泛型函数
const defaultPair = createPair("Default");
console.log(defaultPair); // 输出: { key: 'Default', value: 0 }
const customPair = createPair<number, string>(1, "One");
console.log(customPair); // 输出: { key: 1, value: 'One' }
在此例中,createPair
函数具有默认类型参数。当未指定类型时,使用默认值。第一个调用使用了默认类型,而第二个调用则显式指定了类型。
泛型函数例子
下面是一个使用 TypeScript 编写的泛型排序方法,该方法可以对具有年龄属性的对象数组进行排序。示例中包括 Animal
和 Person
两个接口,它们都有一个 age
属性。通过泛型函数,您可以轻松地对这些对象进行排序。
typescript">// 定义 Animal 接口,包含 age 属性
interface Animal {
name: string;
age: number; // 年龄属性
}
// 定义 Person 接口,包含 age 属性
interface Person {
firstName: string;
lastName: string;
age: number; // 年龄属性
}
// 泛型排序函数,接收一个对象数组和一个比较函数
function sortByAge<T extends { age: number }>(arr: T[], ascending: boolean = true): T[] {
// 使用 Array.sort 方法进行排序
return arr.sort((a, b) => {
// 比较年龄属性
if (a.age < b.age) {
return ascending ? -1 : 1; // 如果需要升序,则返回 -1,反之返回 1
} else if (a.age > b.age) {
return ascending ? 1 : -1; // 如果需要升序,则返回 1,反之返回 -1
} else {
return 0; // 年龄相等,返回 0
}
});
}
// 示例:创建 Animal 对象数组
const animals: Animal[] = [
{ name: "Dog", age: 5 },
{ name: "Cat", age: 3 },
{ name: "Elephant", age: 10 }
];
// 示例:创建 Person 对象数组
const persons: Person[] = [
{ firstName: "Alice", lastName: "Johnson", age: 30 },
{ firstName: "Bob", lastName: "Smith", age: 25 },
{ firstName: "Charlie", lastName: "Brown", age: 35 }
];
// 对动物按年龄升序排序
const sortedAnimals = sortByAge(animals);
console.log("Sorted Animals (Ascending):", sortedAnimals);
// 对人按年龄降序排序
const sortedPersons = sortByAge(persons, false);
console.log("Sorted Persons (Descending):", sortedPersons);
代码说明:
-
接口定义:
Animal
和Person
接口分别定义了动物和人类对象的结构,包含一个age
属性。
-
泛型排序函数:
sortByAge
函数是一个泛型函数,接受一个对象数组arr
和一个布尔值ascending
作为参数,默认为升序。- 使用
Array.sort
方法对数组进行排序。 - 比较对象的
age
属性,返回相应的排序值。
-
示例数据:
- 创建了一个动物数组
animals
和一个人类数组persons
。
- 创建了一个动物数组
-
排序调用:
- 使用
sortByAge
函数对动物数组进行升序排序,并对人类数组进行降序排序。
- 使用
输出示例:
运行该代码后,您将看到排序后的动物和人类对象数组的输出。
学习总结
本次学习了接口、类、对象和泛型四大概念。分别如下:
1、深入理解 TypeScript 接口的定义、联合类型、数组使用以及接口继承的特性。
2、TypeScript 类的定义、实例化、继承、方法重写以及接口实现等特性。
3、TypeScript 中对象的定义和使用,包括如何创建对象、访问其属性、添加方法以及将对象作为函数参数。
4、泛型是 TypeScript 中一个重要的特性,它使得编写可重用、灵活且类型安全的代码成为可能。通过使用泛型函数、接口和类,开发者可以有效地处理多种类型的数据,提高代码的清晰度和可维护性。
其中接口是一系列抽象方法的声明,是一些方法特征的集合,这些方法都应是抽象的。其次由类实现接口的抽象方法。
类可以包含以下几个模块(类的数据成员):
- 字段 − 字段是类里面声明的变量。字段表示对象的有关数据。
- 构造函数 − 类实例化时调用,可以为类的对象分配内存。
- 方法 − 方法为对象要执行的操作。
对象是包含一组键值对的实例,其值可以是标量、函数、数组、对象等
泛型(Generics)是一种编程语言特性,允许在定义函数、类、接口等时使用占位符来表示类型,而不是具体的类型。
使用泛型的主要目的是为了处理不特定类型的数据,使得代码可以适用于多种数据类型而不失去类型检查。
泛型的优势包括:
- 代码重用: 可以编写与特定类型无关的通用代码,提高代码的复用性。
- 类型安全: 在编译时进行类型检查,避免在运行时出现类型错误。
- 抽象性: 允许编写更抽象和通用的代码,适应不同的数据类型和数据结构。