网站建设开发步骤,衡阳建设网站制作,qq群短链接生成,济南网站建设需要多少钱泛型#xff1a;代码的变色龙 #x1f98e;
为什么需要泛型#xff1f;
想象一个快递员#xff0c;每天要处理不同类型的包裹。如果为每种类型的包裹都写一套处理程序#xff0c;那会很麻烦。泛型就像是一个通用的包裹处理系统#xff0c;它能…泛型代码的变色龙
为什么需要泛型
想象一个快递员每天要处理不同类型的包裹。如果为每种类型的包裹都写一套处理程序那会很麻烦。泛型就像是一个通用的包裹处理系统它能智能地适应不同类型的包裹。
让我们通过一个简单的例子来理解
// 没有泛型时我们需要为每种类型写一个函数
function processNumberBox(box: { value: number }) {console.log(box.value 10);
}function processStringBox(box: { value: string }) {console.log(box.value.toUpperCase());
}// 使用泛型后一个函数就能处理所有类型
function processBoxT(box: { value: T }) {console.log(box.value);return box.value;
}// 现在可以处理任何类型
processBox({ value: 42 }); // 处理数字
processBox({ value: hello }); // 处理字符串
processBox({ value: true }); // 处理布尔值
泛型就像变量的变量
// 创建一个通用的盒子类
class BoxT {private content: T;constructor(value: T) {this.content value;}getValue(): T {return this.content;}
}// 创建不同类型的盒子
const numberBox new Box(123); // 数字盒子
const stringBox new Box(hello); // 字符串盒子
const dateBox new Box(new Date()); // 日期盒子// TypeScript 会自动推断并确保类型安全
numberBox.getValue().toFixed(2); // ✅ 可以因为是数字
stringBox.getValue().toUpperCase(); // ✅ 可以因为是字符串
实际应用场景
创建通用数据结构
// 创建一个通用的盒子类
class BoxT {private content: T;constructor(value: T) {this.content value;}getValue(): T {return this.content;}
}// 创建不同类型的盒子
const numberBox new Box(123); // 数字盒子
const stringBox new Box(hello); // 字符串盒子
const dateBox new Box(new Date()); // 日期盒子// TypeScript 会自动推断并确保类型安全
numberBox.getValue().toFixed(2); // ✅ 可以因为是数字
stringBox.getValue().toUpperCase(); // ✅ 可以因为是字符串
numberBox.getValue().toUpperCase(); // ❌ 错误数字没有toUpperCase方法
API响应处理
// 通用的API响应处理器
interface ApiResponseT {success: boolean;data: T;message: string;
}// 用户接口
interface User {id: number;name: string;
}// 使用泛型处理不同类型的响应
async function fetchUser(): PromiseApiResponseUser {// ... API调用return {success: true,data: { id: 1, name: 张三 },message: 获取成功};
}
类型守卫代码的安检员
什么是类型守卫
想象你是一个夜店保安需要检查进入的人是否满足条件年龄、着装等。类型守卫就是代码世界的保安它帮助我们在运行时确保数据类型的正确性。
// 定义可能的类型
type Animal Bird | Dog;interface Bird {type: bird;flySpeed: number;
}interface Dog {type: dog;runSpeed: number;
}// 类型守卫函数
function isBird(animal: Animal): animal is Bird {return animal.type bird;
}// 使用类型守卫
function moveAnimal(animal: Animal) {if (isBird(animal)) {// TypeScript现在知道这是一只鸟console.log(飞行速度${animal.flySpeed});} else {// TypeScript知道这是一只狗console.log(奔跑速度${animal.runSpeed});}
}
常见的类型守卫方式
typeof 守卫
function process(value: string | number) {if (typeof value string) {// 这里TypeScript知道value是字符串return value.toUpperCase();} else {// 这里TypeScript知道value是数字return value.toFixed(2);}
}
instanceof 守卫
class Car {drive() { console.log(开车); }
}class Bicycle {ride() { console.log(骑行); }
}function useVehicle(vehicle: Car | Bicycle) {if (vehicle instanceof Car) {vehicle.drive();} else {vehicle.ride();}
}
实用工具类型代码的瑞士军刀 ️
TypeScript的工具类型也是这样的一个好用的工具集合
1. PartialT - 所有属性变为可选
interface User {name: string;age: number;email: string;
}// 所有字段都变成可选的
type PartialUser PartialUser;
// 等同于
// {
// name?: string;
// age?: number;
// email?: string;
// }// 实际应用更新用户信息
function updateUser(userId: number, updates: PartialUser) {// 可以只更新部分字段
}
2. RequiredT - 所有属性变为必需
interface Config {name?: string;timeout?: number;
}// 所有字段都变成必需的
type RequiredConfig RequiredConfig;
// 等同于
// {
// name: string;
// timeout: number;
// }
实际应用创建表单验证规则
type ValidationRulesT {[K in keyof T]: {required?: boolean;minLength?: number;maxLength?: number;pattern?: RegExp;}
}// 使用
const employeeValidation: ValidationRulesEmployee {name: { required: true, minLength: 2 },salary: { required: true, pattern: /^\d$/ },department: { required: true }
};
映射类型批量加工属性
想象你有一个印章可以给所有属性都盖上只读的标记
// 原始接口
interface Employee {name: string;salary: number;department: string;
}// 让所有属性只读
type ReadonlyEmployee {readonly [K in keyof Employee]: Employee[K];
}// 让所有属性可选
type OptionalEmployee {[K in keyof Employee]?: Employee[K];
}这些高级类型特性看起来可能有点复杂但它们就像乐高积木一样 - 一旦你理解了基本概念就可以把它们组合起来构建更复杂的结构。这些特性的目的是帮助我们写出更安全、更可维护的代码。