前端人速存!10 个 TypeScript 实战技巧让代码会 “说话”
liuian 2025-05-11 17:05 70 浏览
在React、Vue这些前端框架你追我赶卷性能的当下,TypeScript早已悄悄成为众多项目的 “幕后英雄”。但说实话,不少兄弟在和它打交道时,都被类型报错折磨得够呛 —— 明明代码逻辑没问题,为啥就是通不过编译?别急!今天就掏出 10 个压箱底的实战技巧,手把手教你驯服这个 “代码质检员”!
让类型自己 “开口报身份”:字面量类型的魔法
你可能会发现,写代码时经常遇到某个变量只能取固定值的情况。举个例子,订单状态只有 “待支付”“已发货”“已完成” 三种,要是用普通字符串类型,一不小心就可能传进个 “已取消” 导致逻辑错乱。这时候,字面量类型就派上用场了!
// 定义订单状态的字面量类型,明确限定取值范围
type OrderStatus = '待支付' | '已发货' | '已完成';
// 声明订单对象,status属性只能是上述三种值
const order = {
id: 1,
status: '待支付' as OrderStatus
};
// 尝试赋值非法状态会直接报错!
// order.status = '已取消'; // 编译时就会报错
是不是很神奇?通过这种方式,代码自己就能 “告诉” 你哪些值是合法的,提前拦截掉一大波潜在 Bug。
泛型:代码界的 “万能模板”
泛型这玩意儿,初次接触确实有点抽象,但掌握了它,你会发现写代码就像开了挂!想象你要写个函数,既能处理数字数组求和,又能处理字符串数组拼接,要是不用泛型,可能得写两个函数 —— 太麻烦了!
// 定义一个通用函数,T代表待确定的类型
function handleArray<T>(arr: T[]): T[] {
// 这里可以对数组进行各种操作,比如反转
return arr.reverse();
}
const numArr = [1, 2, 3];
const strArr = ['a', 'b', 'c'];
// 调用函数时,TypeScript会根据传入的参数自动推导类型
const reversedNumArr = handleArray(numArr);
const reversedStrArr = handleArray(strArr);
为什么这个方法有效?关键在于泛型允许你先 “占位”,等实际调用时再确定具体类型。就像拿着空白模板,不管是数字、字符串还是自定义对象,都能往里套!
接口 VS 类型别名:选对工具事半功倍
这俩兄弟经常让新手犯迷糊 —— 到底啥时候用接口,啥时候用类型别名?去年我们团队遇到一个典型案例:开发电商后台时,需要定义用户信息,一开始用类型别名快速搞定。结果后期要给管理员用户扩展权限字段,类型别名就显得力不从心了。
// 用接口定义基础用户类型
interface User {
name: string;
age: number;
}
// 扩展接口,定义管理员用户类型
interface AdminUser extends User {
role: 'admin';
permissions: string[];
}
// 类型别名定义简单联合类型
type StringOrNumber = string | number;
要特别警惕的是:如果需要继承、扩展,优先选接口;只是组合已有类型,类型别名更轻便。
类型断言:和 TypeScript 的 “私下约定”
有时候你心里清楚某个变量的真实类型,但 TypeScript 就是 “认死理” 不给通过。这时候就需要类型断言,和它来个 “私下约定”。
// 获取DOM元素,TypeScript默认认为是HTMLElement类型
const element = document.getElementById('myButton');
// 通过类型断言,告诉TypeScript这是个HTMLButtonElement
const button = element as HTMLButtonElement;
button.addEventListener('click', () => {
console.log('按钮被点击');
});
不过得悠着点用!毕竟这相当于跳过了类型检查,如果判断错误,运行时可能会出大问题。
交叉类型:合并类型的 “超级胶水”
想象你要开发一个既具备用户属性,又有管理员权限的 “超级用户” 类型,该怎么办?交叉类型就是答案!
// 定义用户类型
interface RegularUser {
name: string;
age: number;
}
// 定义管理员类型
interface Admin {
role: 'admin';
permissions: string[];
}
// 使用交叉类型合并两个类型
type SuperUser = RegularUser & Admin;
const superUser: SuperUser = {
name: 'adminUser',
age: 30,
role: 'admin',
permissions: ['create', 'delete']
};
令人惊讶的是,通过交叉类型,你能快速组合多个类型的特性,让代码结构更清晰。
可选链操作符:防 “undefined” 的终极武器
在处理多层嵌套对象时,最怕某个属性突然 “消失” 导致报错。举个例子,获取用户地址的门牌号,如果用户没填地址,直接访问user.address.houseNumber就会引发TypeError。
interface User {
name: string;
address?: {
street: string;
houseNumber?: number;
};
}
const user: User = {
name: 'test',
address: {
street: '123 Road'
}
};
// 使用可选链操作符,安全获取门牌号,不存在时返回undefined
const houseNumber = user.address?.houseNumber;
console.log(houseNumber);
这就涉及到一个关键点:可选链操作符会在属性不存在时自动 “短路”,避免深层访问报错,堪称处理不确定数据的必备神器!
函数重载:让函数 “见人说人话”
有时候一个函数需要根据不同参数类型,返回不同类型的值。比如一个parse函数,传入字符串时解析成对象,传入对象时直接返回。
// 声明函数重载签名,定义不同参数和返回值类型
function parse(data: string): object;
function parse(data: object): object;
// 实现函数,根据传入参数类型处理逻辑
function parse(data: string | object): object {
if (typeof data ==='string') {
return JSON.parse(data);
}
return data;
}
const str = '{"name": "test"}';
const obj = { name: 'test' };
const result1 = parse(str);
const result2 = parse(obj);
经过验证的最佳实践是:通过函数重载,能让函数在不同场景下表现得更 “智能”,同时保留清晰的类型定义。
索引签名:动态属性的 “安全网”
开发配置项管理功能时,经常遇到属性名不固定的情况。要是用普通接口定义,新增属性就会报错。
// 定义包含索引签名的接口,允许任意字符串属性名
interface Config {
[key: string]: string | number;
}
const config: Config = {
name: 'app',
version: 1.0
};
// 动态添加属性也不会报错
config.env = 'production';
有了索引签名,就像给对象装了个 “弹性容器”,既能限制属性值类型,又能灵活扩展属性。
条件类型:类型界的 “智能开关”
在处理数据转换时,经常需要根据不同条件生成不同类型。比如将数组中的元素类型转换为可选类型。
// 定义条件类型,T为传入类型
type MakeOptional<T> = {
[P in keyof T]?: T[P];
};
interface Person {
name: string;
age: number;
}
// 使用条件类型,将Person类型转换为所有属性可选
type OptionalPerson = MakeOptional<Person>;
const optionalPerson: OptionalPerson = {};
为啥它这么好用?因为条件类型能在类型层面做逻辑判断,实现动态类型转换,大大提升代码的灵活性。
命名空间:代码的 “收纳大师”
项目大了之后,各种类型定义、函数声明混在一起,找起来特别费劲。这时候命名空间就像个 “收纳盒”,把相关代码规整得明明白白。
// 定义命名空间,存放用户相关代码
namespace UserModule {
export interface User {
name: string;
age: number;
}
export function getUser(): User {
return { name: 'test', age: 30 };
}
}
// 使用命名空间中的类型和函数
const user: UserModule.User = UserModule.getUser();
必须强调的是:合理使用命名空间,能有效避免命名冲突,让项目结构更清晰,维护起来也更轻松!
掌握这 10 个技巧,TypeScript基本就能被你拿捏得死死的!不过话说回来,有的开发者觉得类型检查太严格,影响开发效率;也有人认为严格类型才是代码质量的保障。你在项目里是更倾向 “严格模式”,还是喜欢 “适度宽松” 呢?欢迎在评论区聊聊你的实战经验!
相关推荐
- 教你把多个视频合并成一个视频的方法
-
一.情况介绍当你有一个m3u8文件和一个目录,目录中有连续的视频片段,这些片段可以连成一段完整的视频。m3u8文件打开后像这样:m3u8文件,可以理解为播放列表,里面是播放视频片段的顺序。视频片段像这...
- 零代码编程:用kimichat合并一个文件夹下的多个文件
-
一个文件夹里面有很多个srt字幕文件,如何借助kimichat来自动批量合并呢?在kimichat对话框中输入提示词:你是一个Python编程专家,完成如下的编程任务:这个文件夹:D:\downloa...
- Java APT_java APT 生成代码
-
JavaAPT(AnnotationProcessingTool)是一种在Java编译阶段处理注解的工具。APT会在编译阶段扫描源代码中的注解,并根据这些注解生成代码、资源文件或其他输出,...
- Unit Runtime:一键运行 AI 生成的代码,或许将成为你的复制 + 粘贴神器
-
在我们构建了UnitMesh架构之后,以及对应的demo之后,便着手于实现UnitMesh架构。于是,我们就继续开始UnitRuntime,以用于直接运行AI生成的代码。PS:...
- 挣脱臃肿的枷锁:为什么说Vert.x是Java开发者手中的一柄利剑?
-
如果你是一名Java开发者,那么你的职业生涯几乎无法避开Spring。它如同一位德高望重的老国王,统治着企业级应用开发的大片疆土。SpringBoot的约定大于配置、SpringCloud的微服务...
- 五年后,谷歌还在全力以赴发展 Kotlin
-
作者|FredericLardinois译者|Sambodhi策划|Tina自2017年谷歌I/O全球开发者大会上,谷歌首次宣布将Kotlin(JetBrains开发的Ja...
- kotlin和java开发哪个好,优缺点对比
-
Kotlin和Java都是常见的编程语言,它们有各自的优缺点。Kotlin的优点:简洁:Kotlin程序相对于Java程序更简洁,可以减少代码量。安全:Kotlin在类型系统和空值安全...
- 移动端架构模式全景解析:从MVC到MVVM,如何选择最佳设计方案?
-
掌握不同架构模式的精髓,是构建可维护、可测试且高效移动应用的关键。在移动应用开发中,选择合适的软件架构模式对项目的可维护性、可测试性和团队协作效率至关重要。随着应用复杂度的增加,一个良好的架构能够帮助...
- 颜值非常高的XShell替代工具Termora,不一样的使用体验!
-
Termora是一款面向开发者和运维人员的跨平台SSH终端与文件管理工具,支持Windows、macOS及Linux系统,通过一体化界面简化远程服务器管理流程。其核心定位是解决多平台环境下远程连接、文...
- 预处理的底层原理和预处理编译运行异常的解决方案
-
若文章对您有帮助,欢迎关注程序员小迷。助您在编程路上越走越好![Mac-10.7.1LionIntel-based]Q:预处理到底干了什么事情?A:预处理,顾名思义,预先做的处理。源代码中...
- 为“架构”再建个模:如何用代码描述软件架构?
-
在架构治理平台ArchGuard中,为了实现对架构的治理,我们需要代码+模型描述所要处理的内容和数据。所以,在ArchGuard中,我们有了代码的模型、依赖的模型、变更的模型等,剩下的两个...
- 深度解析:Google Gemma 3n —— 移动优先的轻量多模态大模型
-
2025年6月,Google正式发布了Gemma3n,这是一款能够在2GB内存环境下运行的轻量级多模态大模型。它延续了Gemma家族的开源基因,同时在架构设计上大幅优化,目标是让...
- 比分网开发技术栈与功能详解_比分网有哪些
-
一、核心功能模块一个基本的比分网通常包含以下模块:首页/总览实时比分看板:滚动展示所有正在进行的比赛,包含比分、比赛时间、红黄牌等关键信息。热门赛事/焦点战:突出显示重要的、关注度高的比赛。赛事导航...
- 设计模式之-生成器_一键生成设计
-
一、【概念定义】——“分步构建复杂对象,隐藏创建细节”生成器模式(BuilderPattern):一种“分步构建型”创建型设计模式,它将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建...
- 构建第一个 Kotlin Android 应用_kotlin简介
-
第一步:安装AndroidStudio(推荐IDE)AndroidStudio是官方推荐的Android开发集成开发环境(IDE),内置对Kotlin的完整支持。1.下载And...
- 一周热门
-
-
【验证码逆向专栏】vaptcha 手势验证码逆向分析
-
Psutil + Flask + Pyecharts + Bootstrap 开发动态可视化系统监控
-
一个解决支持HTML/CSS/JS网页转PDF(高质量)的终极解决方案
-
再见Swagger UI 国人开源了一款超好用的 API 文档生成框架,真香
-
网页转成pdf文件的经验分享 网页转成pdf文件的经验分享怎么弄
-
C++ std::vector 简介
-
飞牛OS入门安装遇到问题,如何解决?
-
系统C盘清理:微信PC端文件清理,扩大C盘可用空间步骤
-
10款高性能NAS丨双十一必看,轻松搞定虚拟机、Docker、软路由
-
python使用fitz模块提取pdf中的图片
-
- 最近发表
- 标签列表
-
- python判断字典是否为空 (50)
- crontab每周一执行 (48)
- aes和des区别 (43)
- bash脚本和shell脚本的区别 (35)
- canvas库 (33)
- dataframe筛选满足条件的行 (35)
- gitlab日志 (33)
- lua xpcall (36)
- blob转json (33)
- python判断是否在列表中 (34)
- python html转pdf (36)
- 安装指定版本npm (37)
- idea搜索jar包内容 (33)
- css鼠标悬停出现隐藏的文字 (34)
- linux nacos启动命令 (33)
- gitlab 日志 (36)
- adb pull (37)
- python判断元素在不在列表里 (34)
- python 字典删除元素 (34)
- vscode切换git分支 (35)
- python bytes转16进制 (35)
- grep前后几行 (34)
- hashmap转list (35)
- c++ 字符串查找 (35)
- mysql刷新权限 (34)