当前位置: 首页 > news >正文

TypeScript - 类型断言 Type Assertion(通俗易懂的详细教程)

前言

有时候你会遇到这样的情况,你会比 TypeScript 更了解某个值的详细信息。通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。类型断言好比其他语言里的类型转换,但是不进行特殊的数据检查和解构。它没有运行时的影响,只是在编译阶段起作用。

在 Typescript 中,会将某些变量具体为某种类型的变量,以此来规范变量的类型。

但是总有些时候一个变量我们不清楚他到底是属于哪种具体的类型,就比如:

// 将 a 变量规范为 string 类型leta:string='a'// 我们想将一个 number 赋值给 a// 这确实是业务逻辑,但是在 typescript 中是不允许的,会报错!a=1

您看,我们想将一个 number 赋值给 a,但 Typescript 死活报错,而断言就可以解决它!

断言语法

如果大家是 React 项目,在使用类型断言时建议使用值 as 类型写法,具体可见官方。

后面会有体现,很简单。

值 as 类型 或者 <类型>值

基本用法

说白了,类型断言(Type Assertion)就是说您可以用来手动指定一个值的类型

例如,以下这个典型的例子:

// 联合类型leta:string|number// 通过断言,这样就不会报错了letb:number=(<string>a).length

您自己知道,您想取得 a 的长度,但是 typescript不清楚 a 到底是 string 还是 number 类型。

而作为 number 类型是没有 length 这个属性的,所以会报错,但是作为开发者的我们是肯定他最后是个 string 的。这时候就可以使用断言将 a 指定为 string 类型。

将任何一个类型断言为 any

不了解 any 类型的朋友,可以参考 这篇博文。

在很多时候, 在 js 中我们会这样为一个对象新增属性。这是很常见的, 也是很方便的一种新增属性的方法,如下所示:

constobj={}obj.name='lwx'obj.job='lol player'

很遗憾,但是在 Typescript 中却会编译报错。因为在 obj 对象上是没有 name 和 obj 两个属性的,所以会报错。

如下所示:

constobj:object={}obj.name='lwx'// error 报错 类型“{}”上不存在属性“name”。obj.job='lol player'// error 报错 类型“{}”上不存在属性“job”。

但是我们自己,100% 确认以及肯定这样的代码是不会报错的(因为我们下一步就是添加这两个属性)。

我们可以使用断言来处理这样的代码。我们临时将 obj 断言成 any 类型, 在 any 类型上访问任何属性都是允许的。

如下代码所示:

constobj:object={};(<any>obj).name='lwx';//通过(<any>obj).job='lol player';//通过

将 any 断言为精准的类型

有时候以为一些历史原因, 又或者是前任的代码原因等滥用 any 的代码,我们可以选择进行优化。

如下面的代码,参数是 any,返回值是 any。这意味着函数的参数、返回值可以是任意类型,非常可怕。

functiongetLength(val:any):any{returnval.length}

您可以进行改进(当然,原代码我们不会去修改),只不过在调用的时候,将参数和返回值断言成精确的值。

functiongetLength(val:any):any{returnval.length}constlen=<number>getLength(<string>'lwx')console.log(len)

这样 len 的类型推导出来就是 number,即结果是数值型。还有函数的参数,断言成 string 字符串进行 “约束”。

将一个联合类型断言成其中一个类型

需要注意的是,断言只能 “欺骗” Typescript 编译器,无法避免运行时的错误,所以请勿滥用断言。

看下面的代码,如果 a 为 string 类型, 那么我就想取 a 的长度,否则我转换下类型再取。

leta:string|number=1// 【如果不将 a 断言成 string 就会报错】// if (typeof a === 'string') {// console.log(a).length) // 如果这样写就会报错 ,需要像下面这样将 `a` 断言成 `string`// }if(typeofa==='string'){console.log((<string>a).length)}if(typeofa==='number'){console.log(String(a).length)}

例如下面代码,本意是想取字符串的第一个字符:

functiongetFirst(val:string|number):string{return(<string>val).substr(0,1)}getFirst(3)

在 Typescript编译的时候并不会报错,但是运行时确报错了。

Uncaught TypeError: val.substr is not a function at getFirst (index.js:133) at index.js:135

原因是(<string>val).substr(0, 1)这串代码直接将 val 变量断言成 string 类型了,却没有考虑到它也可能为 number 类型。

而 Typescript 编译器一看这里是断言,也不校验这里的类型了。

也就是说,断言只能 “欺骗” Typescript 编译器,无法避免运行时的错误,所以请勿滥用断言。

确定赋值断言

在 TypeScript 2.7 版本中引入了确定赋值断言,即允许在实例属性和变量声明后面放置一个 ! 号,从而告诉 TypeScript 该属性会被明确地赋值。

为了更好地理解它的作用,我们来看个具体的例子:

letx:number;initialize();// Variable 'x' is used before being assigned.(2454)console.log(2*x);// Errorfunctioninitialize(){x=10;}

明显该异常信息是说变量 x 在赋值前被使用了,要解决该问题,我们可以使用确定赋值断言:

letx!:number;initialize();console.log(2*x);// Okfunctioninitialize(){x=10;}

通过let x!: number;确定赋值断言,TypeScript 编译器就会知道该属性会被明确地赋值。

非空断言

在上下文中当类型检查器无法断定类型时,一个新的后缀表达式操作符 ! 可以用于断言操作对象是非 null 和非 undefined 类型。具体而言,x! 将从 x 值域中排除 null 和 undefined 。

那么非空断言操作符到底有什么用呢?下面我们先来看一下非空断言操作符的一些使用场景。

1. 忽略 undefined 和 null 类型

functionmyFunc(maybeString:string|undefined|null){// Type 'string | null | undefined' is not assignable to type 'string'.// Type 'undefined' is not assignable to type 'string'.constonlyString:string=maybeString;// ErrorconstignoreUndefinedAndNull:string=maybeString!;// Ok}

2. 调用函数时忽略 undefined 类型

typeNumGenerator=()=>number;functionmyFunc(numGenerator:NumGenerator|undefined){// Object is possibly 'undefined'.(2532)// Cannot invoke an object which is possibly 'undefined'.(2722)constnum1=numGenerator();// Errorconstnum2=numGenerator!();//OK}

因为 ! 非空断言操作符会从编译生成的 JavaScript 代码中移除,所以在实际使用的过程中,要特别注意。比如下面这个例子:

consta:number|undefined=undefined;constb:number=a!;console.log(b);

以上 TS 代码会编译生成以下 ES5 代码:

"use strict";consta=undefined;constb=a;console.log(b);

虽然在 TS 代码中,我们使用了非空断言,使得const b: number = a!;语句可以通过 TypeScript 类型检查器的检查。

但在生成的 ES5 代码中,! 非空断言操作符被移除了,所以在浏览器中执行以上代码,在控制台会输出 undefined。

http://www.jsqmd.com/news/421908/

相关文章:

  • 政企优选!2026银狐(SilverFox)病毒防护服务公司推荐排行 重保级防护/漏洞溯源/全球化服务 - 极欧测评
  • 计算机毕业设计springboot古镇旅游路线规划网站 SpringBoot框架下的历史文化名镇智能导览与行程定制平台 基于SpringBoot的传统村落文化旅游数字化服务系统
  • 2026银狐(SilverFox)病毒防护服务公司推荐排行 实力优选榜 精准查杀/智能防御/全行业适配 - 极欧测评
  • Typescript - type 类型别名(通俗易懂教程)
  • 2026年2月切角热收缩包装机工厂推荐,实力品牌深度解析采购无忧之选 - 品牌鉴赏师
  • 【咕咕咕】CF2200
  • 2026银狐(SilverFox)病毒防护服务公司推荐排行 技术标杆榜 AI溯源/全链防护/多终端适配 - 极欧测评
  • Codeforces K. Similarity (Hard Version)题解
  • 2026年2月封切收缩机厂家推荐:一站式包装解决方案提供商 - 品牌鉴赏师
  • 大数据领域数据架构的Kubernetes容器编排系统应用
  • 开发具有视觉常识推理能力的AI Agent
  • 菜谱合集
  • 题解:洛谷 B2034 计算 2 的幂
  • VSCode每过几秒就提示未响应
  • 神经网络之激活函数
  • 题解:洛谷 B2033 A*B 问题
  • 题解:洛谷 B2031 计算三角形面积
  • WC2026XKLJIU5IGGNOI;hgggggggggg904yyyyyyyyyyyyyyyyyvo RIHFEacsmPo=
  • 高效盘活闲置资源,大量小额天猫超市卡回收渠道全解析 - 京顺回收
  • OpenClaw:零门槛AI自动化神器
  • 月薪 3800 辅警小奇:一年内恋爱结婚,如今即将迎来双胞胎宝宝
  • NR 下行功率分配
  • C++游戏开发之旅 19
  • 相控超声波换能器:原理、应用与完整项目案例详解
  • Linux驱动编译(Out-Of-Tree 交叉编译)
  • 【开题答辩全过程】以 华远企业的员工行为及属性的数据分析与可视化为例,包含答辩的问题和答案
  • 最小二乘问题详解11:基于李代数的PnP优化
  • EB(EdgeBus)如何低成本实现传感器到 LoRaWAN 的智能对接?
  • 题解:洛谷 B2030 计算线段长度
  • 日语视频 SRT 字幕生成软件下载:日语视频本地自动翻译SRT字幕生成、日语视频自动翻译 Faster Whisper v1.7 下载与使用教程(含AMD显卡支持)