【TS】TypeScript类型断言:掌握类型转换的艺术


鑫宝Code

🌈个人主页: 鑫宝Code
🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础
💫个人格言: "如无必要,勿增实体"


文章目录

  • TypeScript类型断言:掌握类型转换的艺术
    • 1. 引言
    • 2. 什么是类型断言?
    • 3. 类型断言的基本语法
      • 3.1 尖括号语法
      • 3.2 as语法
    • 4. 类型断言的常见用途
      • 4.1 处理any类型
      • 4.2 处理联合类型
      • 4.3 在类型收窄中使用
    • 5. 双重断言
    • 6. const断言
    • 7. 非空断言
    • 8. 类型断言与类型转换的区别
    • 9. 类型断言的最佳实践
    • 10. 类型断言的潜在风险
    • 11. 高级用例:类型断言在泛型中的应用
    • 12. 类型断言与接口
    • 13. 实际应用示例
    • 14. 结论

TypeScript类型断言:掌握类型转换的艺术

1. 引言

在TypeScript的类型系统中,类型断言是一个强大而有用的特性。它允许开发者告诉编译器某个值的具体类型,即使TypeScript无法自动推断出这个类型。本文将深入探讨TypeScript中的类型断言,包括其定义、使用方法、最佳实践以及注意事项,帮助您更好地理解和应用这一重要概念。
在这里插入图片描述

2. 什么是类型断言?

类型断言是一种告诉编译器"相信我,我知道我在做什么"的方式。它类似于其他语言中的类型转换,但不进行特殊的数据检查和重构。类型断言纯粹是一个编译时语法,不会影响程序的运行时行为。

3. 类型断言的基本语法

TypeScript提供了两种语法来进行类型断言:

3.1 尖括号语法

let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;

3.2 as语法

let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

注意:在JSX中,只能使用as语法。

4. 类型断言的常见用途

4.1 处理any类型

当处理any类型的数据时,类型断言可以帮助我们恢复类型检查:

function getLength(something: any): number {if (something as string) {return (something as string).length;}return 0;
}

4.2 处理联合类型

当处理联合类型时,类型断言可以帮助我们访问特定类型的属性:

interface Bird {fly(): void;layEggs(): void;
}interface Fish {swim(): void;layEggs(): void;
}function getSmallPet(): Fish | Bird {// ...
}let pet = getSmallPet();
(pet as Fish).swim();

4.3 在类型收窄中使用

类型断言可以在类型守卫之外进行类型收窄:

function isString(value: unknown): value is string {return typeof value === 'string';
}function processValue(value: unknown) {if (isString(value)) {console.log(value.toUpperCase());} else {console.log(value as number * 2);}
}

5. 双重断言

在某些极端情况下,我们可能需要使用双重断言:

function handleEvent(event: Event) {const mouseEvent = event as unknown as MouseEvent;console.log(mouseEvent.clientX, mouseEvent.clientY);
}

注意:双重断言应该非常谨慎地使用,因为它可能导致运行时错误。

6. const断言

TypeScript 3.4引入了const断言,它可以让我们创建完全不可变的类型:

let x = "hello" as const;
// Type is literally "hello"let arr = [1, 2, 3] as const;
// Type is readonly [1, 2, 3]

7. 非空断言

在这里插入图片描述

非空断言操作符 ! 可以用来断言一个表达式的值不为null或undefined:

function getValue(): string | null {return Math.random() > 0.5 ? "Hello" : null;
}const value = getValue();
console.log(value!.toUpperCase());

8. 类型断言与类型转换的区别

类型断言只在编译时起作用,不会进行任何运行时的类型检查或转换:

let num: any = "123";
let numAsNumber = num as number;
// numAsNumber的类型是number,但它的值仍然是字符串"123"

相比之下,类型转换会在运行时进行实际的值转换:

let num: any = "123";
let numAsNumber = Number(num);
// numAsNumber的类型是number,它的值是数字123

9. 类型断言的最佳实践

  1. 优先使用类型守卫:当可能的时候,使用类型守卫而不是类型断言。类型守卫提供了运行时的类型检查。

    function isString(value: unknown): value is string {return typeof value === 'string';
    }function processValue(value: unknown) {if (isString(value)) {console.log(value.toUpperCase());}
    }
    
  2. 避免过度使用any:尽量不要使用any类型,而是使用更具体的类型或unknown。

  3. 使用as const来创建字面量类型:当你想要TypeScript推断出最具体的类型时,使用as const。

  4. 谨慎使用非空断言:只在你确定值不会是null或undefined时使用非空断言。

  5. 在JSX中使用as语法:在JSX中,只能使用as语法进行类型断言。

10. 类型断言的潜在风险

虽然类型断言是一个强大的工具,但它也带来了一些潜在的风险:

  1. 运行时错误:类型断言可能导致运行时错误,因为它绕过了TypeScript的类型检查。

    let num: any = "not a number";
    let square = (num as number) * (num as number);
    // 这会在运行时抛出错误
    
  2. 隐藏类型错误:过度使用类型断言可能会隐藏真正的类型错误,使代码更难维护。

  3. 破坏类型安全:不恰当的类型断言可能会破坏TypeScript提供的类型安全保证。

11. 高级用例:类型断言在泛型中的应用

类型断言在处理泛型时特别有用:

function create<T>(Class: { new(): T }): T {return new Class();
}class Lion {roar() {console.log('Roar!');}
}const lion = create(Lion) as Lion;
lion.roar(); // OK

12. 类型断言与接口

类型断言可以帮助我们在使用接口时更灵活:

interface SquareConfig {color?: string;width?: number;[propName: string]: any;
}function createSquare(config: SquareConfig): { color: string; area: number } {return {color: config.color || "red",area: config.width ? config.width * config.width : 20,};
}let mySquare = createSquare({ colour: "red", width: 100 } as SquareConfig);

13. 实际应用示例

让我们通过一个实际的应用示例来展示类型断言的使用:

// 假设我们从API获取了一些数据
interface ApiResponse {data: unknown;status: number;
}interface User {id: number;name: string;email: string;
}async function fetchUser(id: number): Promise<User> {const response: ApiResponse = await fetch(`/api/users/${id}`).then(res => res.json());if (response.status !== 200) {throw new Error(`Failed to fetch user: ${response.status}`);}// 使用类型断言来处理unknown类型const user = response.data as User;// 进行一些运行时检查if (typeof user.id !== 'number' || typeof user.name !== 'string' || typeof user.email !== 'string') {throw new Error('Invalid user data');}return user;
}// 使用函数
async function displayUserInfo(id: number) {try {const user = await fetchUser(id);console.log(`User ${user.name} (${user.email}) has id ${user.id}`);} catch (error) {console.error(error);}
}displayUserInfo(1);

在这个例子中,我们使用类型断言来处理API返回的unknown类型的数据。我们将其断言为User类型,但同时也进行了运行时检查以确保数据的正确性。这种方法结合了类型断言的灵活性和运行时检查的安全性。

14. 结论

TypeScript的类型断言是一个强大的工具,它允许开发者在特定情况下覆盖TypeScript的类型推断。然而,它应该被谨慎使用,因为过度依赖类型断言可能会导致运行时错误和类型安全问题。

最佳实践是尽可能依赖TypeScript的类型推断和类型守卫,只在必要时使用类型断言。当使用类型断言时,应该确保你比TypeScript编译器更了解值的实际类型。

通过合理使用类型断言,我们可以在保持代码类型安全的同时,处理一些TypeScript类型系统无法自动推断的复杂情况。这使得TypeScript成为一个更加灵活和强大的工具,能够适应各种编程场景。

随着您在实际项目中不断实践,您会发现类型断言是TypeScript工具箱中的一个重要工具,能够帮助您编写更加健壮和可维护的代码。继续探索和学习,相信您会在TypeScript的类型系统中发现更多精彩!

End

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/388289.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

链表的实现(C++版)

对于链表的学习,之前在C语言部分的时候就已经有学习过,也学会了使用C语言来打造一个链表.如今学了C 则想通过C来打造一个链表,以达到锻炼自己的目的. 1.链表的初步实现 1.节点模板的设置 template <class T> struct ListNode{ListNode <T>* _next;ListNode <T…

k8s学习--使用kubepshere部署devops项目时遇到的报错(无法找到gitee仓库)

今天在kubesphere部署devops项目&#xff0c;编辑流水线的时候&#xff0c;发现怎么也访问不到gitee仓库 报错的流水线位置 报错日志 报错原因 变量问题 因为看见了csy/sangomall&#xff0c;所以理所当然的把路径变量GITEE_ACCOUNT写成了用户名 解决方法 结果发现仓库…

可靠的图纸加密软件,七款图纸加密软件推荐

大家好啊,我是小固,今天跟大家聊聊图纸加密软件。 作为一名设计师,我深知保护自己的知识产权有多重要。曾经就因为图纸泄露,差点血本无归,那个教训可真是惨痛啊!所以我今天就给大家推荐几款靠谱的图纸加密软件,希望能帮到你们。 固信软件https://www.gooxion.com/ 首先要隆重…

Java语言程序设计——篇十一(1)

&#x1f33f;&#x1f33f;&#x1f33f;跟随博主脚步&#xff0c;从这里开始→博主主页&#x1f33f;&#x1f33f;&#x1f33f; 欢迎大家&#xff1a;这里是CSDN&#xff0c;我的学习笔记、总结知识的地方&#xff0c;喜欢的话请三连&#xff0c;有问题可以私信&#x1f33…

Vue 的安装与配置

今天是八月一日&#xff0c;我也开启了Vue的学习&#xff0c;希望和大家一起学编程&#xff0c;相互督促&#xff0c;相互进步&#xff01; 安装vscode 安装Node.js 官网&#xff1a;https://nodejs.org/zh-cn 下载完正常安装就行 可以winr输入cmd&#xff0c;也可以vscod…

springboot智能健康管理平台-计算机毕业设计源码57256

摘要 在当今社会&#xff0c;人们越来越重视健康饮食和健康管理。借助SpringBoot框架和MySQL数据库的支持&#xff0c;开发智能健康管理平台成为可能。该平台结合了小程序技术的便利性和SpringBoot框架的快速开发能力&#xff0c;为用户提供了便捷的健康管理解决方案。 通过智能…

【多线程】单例模式

&#x1f3c0;&#x1f3c0;&#x1f3c0;来都来了&#xff0c;不妨点个关注&#xff01; &#x1f3a7;&#x1f3a7;&#x1f3a7;博客主页&#xff1a;欢迎各位大佬! 文章目录 1. 什么是单例模式1.1 理解单例模式1.2 单例模式的特点 2. 饿汉模式3. 懒汉模式3.1 单线程下的懒…

中国人民解放军建军97周年

缅怀先烈&#xff0c;砥砺前行 付吾辈之韶华&#xff0c;耀吾辈之中华! 万里河山&#xff0c;有您心安!

Django REST Framework(十五)路由Routes

如何在Django REST framework中利用SimpleRouter和DefaultRouter来高效生成视图集的路由信息,并详细解释如何使用action装饰器为视图集中的自定义方法生成路由 1.路由的定义规则 路由称为URL(Uniform Resource Locator,统一资源定位符),也可以称为URLconf,是对可以从互联…

【Java题解】杨辉三角—力扣

&#x1f389;欢迎大家收看&#xff0c;请多多支持&#x1f339; &#x1f970;关注小哇&#xff0c;和我一起成长&#x1f680;个人主页&#x1f680; ⭐目前主更 专栏Java ⭐数据结构 ⭐已更专栏有C语言、计算机网络⭐ 题目链接&#xff1a;杨辉三角 目录&#x1f451; ⭐题…

the request was rejected because no multipart boundary was found

文章目录 1. 需求描述2. 报错信息3. 探索过程1. 使用postman 排除后端错误2. 搜索网上的解决方法3. 解决方法 1. 需求描述 想要在前端上传一个PDF 发票&#xff0c;经过后端解析PDF之后&#xff0c;将想要的值自动回填到对应的输入框中 2. 报错信息 org.apache.tomcat.util.…

2024年有哪些开放式耳机值得入手?值得关注的开放式耳机评测大赏

如今&#xff0c;开放式耳机越来越受到人们的关注。2024 年更是涌现出了众多优秀的开放式耳机产品。但在众多选择面前&#xff0c;哪一款耳机的音质更出色&#xff1f;哪一款佩戴起来更舒适&#xff1f;又有哪一款在通话质量和连接性能上表现更优异呢&#xff1f;接下来我将详细…

【Devops】CertD 完全免费、自动申请、自动部署SSL证书一站式管理工具 | 自动化HTTPS | 3个月SSL自动轮换

CertD CertD 是一个免费全自动申请和自动部署更新SSL证书的工具。 后缀D取自linux守护进程的命名风格&#xff0c;意为证书守护进程。 关键字&#xff1a;证书自动申请、证书自动更新、证书自动续期、证书自动续签 一、特性 本项目不仅支持证书申请过程自动化&#xff0c;还…

SpringMVC源码解析(二):请求执行流程

SpringMVC源码系列文章 SpringMVC源码解析(一)&#xff1a;web容器启动流程 SpringMVC源码解析(二)&#xff1a;请求执行流程 目录 前言DispatcherServlet入口一、获取HandlerExcutionChain(包括Handler)1、获取Handler1.1、通过request获取查找路径1.2、通过查找路径获取Han…

找工作很迷茫?程序员的岗位宝典来了!

随着数字化转型进展深入&#xff0c;大量数字化、智能化的岗位相继涌现。 但即使这样&#xff0c;大家依然认为&#xff0c;找到一份合适的工作实在是太&#xff01;难&#xff01;了&#xff01; 调查显示&#xff0c;技术创新和商业模式正在成为助推企业发展的两大动力。同时…

【iOS】——锁

五类锁 锁作为一种非强制的机制&#xff0c;被用来保证线程安全。每一个线程在访问数据或者资源前&#xff0c;要先获取&#xff08;Acquire&#xff09;锁&#xff0c;并在访问结束之后释放&#xff08;Release&#xff09;锁。如果锁已经被占用&#xff0c;其它试图获取锁的…

计算机网络必会面经

1.键入网址到网页显示&#xff0c;期间发生了什么 2.在TCP/IP网络模型中。TCP将数据进行分段后&#xff0c;为什么还需要IP层继续分片 3.详细说明tcp三次握手&#xff0c;为什么是三次&#xff0c;若每次握手丢了&#xff0c;解决办法是什么 4.详细说明tcp四次挥手&#xff…

【Python】python基础

本篇文章将讲解以下知识点&#xff1a; &#xff08;1&#xff09;循环语句 &#xff08;2&#xff09;字符串格式化 &#xff08;3&#xff09;运算符 一&#xff1a;循环语句 循环语句有两种&#xff1a;while for 本篇文章只讲解while循环 格式&#xff1a; whil…

Unity材质球自动遍历所需贴图

Unity材质球自动遍历所需贴图 文章目录 Unity材质球自动遍历所需贴图一、原理二、用法1.代码&#xff1a;2.使用方法 一、原理 例如一个材质球名为&#xff1a;Decal_Text_Cranes_01_Mat &#xff0c; 然后从全局遍历出&#xff1a;Decal_Text_Cranes_01_Albedo赋值给材质球的…

【网络基础】初识网络 {计算机网络背景;网络协议初识;网络传输基本流程;网络中的地址管理;网络设备简单介绍}

一、计算机网络背景 1.1 网络发展 计算机网络的发展可以追溯到20世纪60年代&#xff0c;那时候最初的计算机网络只是为了让科学家们能够共享计算机资源和数据。但是在20世纪80年代&#xff0c;互联网的出现彻底改变了计算机网络的面貌&#xff0c;使得人们可以随时随地通过互…