Typescript基础知识(类型断言、类型别名、字符串字面量类型、枚举、交叉类型)
系列文章目录
引入一:Typescript基础引入(基础类型、元组、枚举)
引入二:Typescript面向对象引入(接口、类、多态、重写、抽象类、访问修饰符)
第一章:Typescript基础知识(Typescript介绍、搭建TypeScript环境、基本数据类型)
第二章:Typescript常用类型(任意值any、数组Array、函数Function、元组Tuple、类型推论、联合类型)
第三章:Typescript基础知识(类型断言、类型别名、字符串字面量类型、枚举、交叉类型)
文章目录
- 系列文章目录
- 一、类型断言
- 1.1 语法
- 1.2 断言的用途
- 1.2.1 将一个联合类型断言为其中一个类型
- 1.2.2 将一个父类断言为更加具体的子类
- 1.2.3 将任何一个类型断言为any
- 1.2.4 将 any 断言为一个具体的类型
- 1.3 非空断言运算符( ! 后缀)
- 1.4 确定赋值断言
- 二、类型别名
- 三、字面量类型
- 3.1 字符串字面量类型
- 3.2 数字字面量类型及布尔字面量类型
- 四、枚举
- 4.1 手动赋值
- 五、交叉类型
一、类型断言
类型断言(Type Assertion)可以用来手动指定一个值的类型。
1.1 语法
值 as 类型
或者
<类型>值
在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用前者,即值 as 类型
,因此我们更推荐使用 as 语法。
形如 的语法在 tsx 中表示的是一个 ReactNode,在ts中除了表示类型断言之外,也可能是表示一个泛型。
1.2 断言的用途
1.2.1 将一个联合类型断言为其中一个类型
- 当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们
只能访问此联合类型的所有类型中共有的属性或方法
。 - 当我们确实需要在还不确定类型的时候就访问其中一个类型特有的属性或方法时,就会报错。
interface Cat {name: string;run(): void;
}
interface Fish {name: string;swim(): void;
}function getName(animal: Cat | Fish) {return animal.name;
}function isFish(animal: Cat | Fish) {if (typeof animal.swim === 'function') {return true;}return false;
}
// index.ts:11:23 - error TS2339: Property 'swim' does not exist on type 'Cat | Fish'.
// Property 'swim' does not exist on type 'Cat'.
此时可以使用类型断言,将 animal 断言成 Fish:
interface Cat {name: string;run(): void;
}
interface Fish {name: string;swim(): void;
}function isFish(animal: Cat | Fish) {if (typeof (animal as Fish).swim === 'function') {return true;}return false;
}
1.2.2 将一个父类断言为更加具体的子类
当类之间有继承关系时,类型断言也是很常见:
class ApiError extends Error {code: number = 0;
}
class HttpError extends Error {statusCode: number = 200;
}function isApiError(error: Error) {if (typeof (error as ApiError).code === 'number') {return true;}return false;
}
上述例子中,由于父类 Error 中没有 code 属性,故直接获取 error.code 会报错,需要使用类型断言获取 (error as ApiError).code。
上述例子中有一个更合适的方式来判断是不是 ApiError,那就是使用 instanceof:
class ApiError extends Error {code: number = 0;
}
class HttpError extends Error {statusCode: number = 200;
}function isApiError(error: Error) {if (error instanceof ApiError) {return true;}return false;
}
但是当 ApiError 和 HttpError 不是一个真正的类
,而是一个 TypeScript 的接口
(interface),接口是一个类型,不是一个真正的值,它在编译结果中会被删除,就无法使用 instanceof 来做运行时判断,此时就只能用类型断言
,通过判断是否存在 code 属性,来判断传入的参数是不是 ApiErro:
interface ApiError extends Error {code: number;
}
interface HttpError extends Error {statusCode: number;
}
/*
function isApiError(error: Error) {if (error instanceof ApiError) {return true;}return false;
}// index.ts:9:26 - error TS2693: 'ApiError' only refers to a type, but is being used as a value here.
*/function isApiError(error: Error) {if (typeof (error as ApiError).code === 'number' ) {return true;}return false;
}
1.2.3 将任何一个类型断言为any
当我们需要将 window 上添加一个属性 foo,但 TypeScript 编译时会报错,提示我们 window 上不存在 foo 属性。
window.foo = 1;// index.ts:1:8 - error TS2339: Property 'foo' does not exist on type 'Window & typeof globalThis'.
此时我们可以使用 as any 临时将 window 断言为 any 类型:
(window as any).foo = 1;
注意: 将一个变量断言为 any 可以说是解决 TypeScript 中类型问题的最后一个手段。它极有可能掩盖了真正的类型错误,所以如果不是非常确定,就不要使用 as any。
1.2.4 将 any 断言为一个具体的类型
开发中,我们不可避免的需要处理 any 类型的变量,遇到 any 类型的变量时,我们可以选择无视它,任由它滋生更多的 any。
我们也可以选择改进它,通过类型断言及时的把 any 断言为精确的类型
:
function getCacheData(key: string): any {return (window as any).cache[key];
}interface Cat {name: string;run(): void;
}const tom = getCacheData('tom') as Cat;
tom.run();
1.3 非空断言运算符( ! 后缀)
在上下文中当类型检查器无法断定类型时,一个新的后缀表达式操作符 ! 可以用于断言操作对象是非 null 和非 undefined 类型。 !
在任何表达式之后写入
代表一种类型断言,即该值不是 null or undefined
:
let mayNullOrUndefinedOrString: null | undefined | string;
mayNullOrUndefinedOrString!.toString(); // ok
mayNullOrUndefinedOrString.toString(); // error
function liveDangerously(x?: number | null) { console.log(x!.toFixed());
}
1.4 确定赋值断言
允许在实例属性和变量声明后面放置一个 ! 号
,从而告诉 TypeScript 该属性会被明确地赋值
。
let x: number;
initialize();console.log(2 * x); // Variable 'x' is used before being assigned.(2454)
function initialize() {x = 10;
}
上述例子中,该异常信息是说变量 x 在赋值前被使用了,要解决该问题,我们可以使用确定赋值断言
let x!: number;
initialize();console.log(2 * x);
function initialize() {x = 10;
}
二、类型别名
类型别名用来给一个类型起个新名字
(类型别名常用于联合类型)
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {if (typeof n === "string") {return n;} else {return n();}
}function test() {return "hello";
}
console.log(getName("zs"));//zs
console.log(getName(test));//hello
三、字面量类型
3.1 字符串字面量类型
字符串字面量类型用来约束取值只能是某几个字符串中的一个。
type Direction = 'up' | 'down';function move(dir: Direction) {console.log(dir)
}
move('up'); // up
move('right'); // error:Argument of type '"right"' is not assignable to parameter of type 'Direction'
相较于使用 string 类型,使用字面量类型可以将函数的参数限定为更具体的类型
。这不仅提升了程序的可读性,还保证了函数的参数类型,可谓一举两得。
3.2 数字字面量类型及布尔字面量类型
数字字面量类型和布尔字面量类型的使用与字符串字面量类型的使用类似,我们可以使用字面量组合的联合类型将函数的参数限定为更具体的类型:
interface Config {size: 'small' | 'big';isEnable: true | false;margin: 0 | 2 | 4;
}let conf: Config = {size: "big",isEnable: true,margin: 1,//error: Type '1' is not assignable to type '0 | 2 | 4'
};
四、枚举
枚举(Enum)类型用于取值被限定在一定范围内的场景.枚举使用 enum
关键字来定义。
枚举成员会被赋值为从 0 开始递增的数字
,同时也会对枚举值到枚举名进行反向映射
。
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};console.log(Days);
/*
{'0': 'Mon','1': 'Tue','2': 'Wed','3': 'The','4': 'Fri','5': 'Sat',Sun: 'text',Mon: 0,Tue: 1,Wed: 2,The: 3,Fri: 4,Sat: 5
}
*/
console.log(Days["Sun"] === 0); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true
console.log(Days["Sat"] === 6); // trueconsole.log(Days[0] === "Sun"); // true
console.log(Days[1] === "Mon"); // true
console.log(Days[2] === "Tue"); // true
console.log(Days[6] === "Sat"); // true
var Days;
(function (Days) {Days[Days["Sun"] = 0] = "Sun";Days[Days["Mon"] = 1] = "Mon";Days[Days["Tue"] = 2] = "Tue";Days[Days["Wed"] = 3] = "Wed";Days[Days["The"] = 4] = "The";Days[Days["Fri"] = 5] = "Fri";Days[Days["Sat"] = 6] = "Sat";
})(Days || (Days = {}));
console.log(Days);
console.log(Days.Sun);
console.log(Days["Mon"]);
console.log(Days["The"]);
console.log(Days[0]);
console.log(Days[1]);
console.log(Days[4]);
4.1 手动赋值
我们也可以给枚举项手动赋值,未手动赋值的枚举项会接着上一个枚举项递增
。如果未手动赋值的枚举项与手动赋值的重复了,TypeScript 是不会察觉到这一点的:
enum Days {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};console.log(Days["Sun"] === 7); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true
console.log(Days["Sat"] === 6); // true
上面的例子中,递增到 3 的时候与前面的 Sun 的取值重复了,但是 TypeScript 并没有报错,导致 Days[3] 的值先是 “Sun”,而后又被 “Wed” 覆盖了。编译的结果是:
var Days;
(function (Days) {Days[Days["Sun"] = 3] = "Sun";Days[Days["Mon"] = 1] = "Mon";Days[Days["Tue"] = 2] = "Tue";Days[Days["Wed"] = 3] = "Wed";Days[Days["Thu"] = 4] = "Thu";Days[Days["Fri"] = 5] = "Fri";Days[Days["Sat"] = 6] = "Sat";
})(Days || (Days = {}));
所以使用的时候需要注意,最好不要出现这种覆盖的情况。
手动赋值的枚举项可以不是数字,可以是其他类型:
enum Color {Red,Green,Blue = "blur",
}
console.log(Color); //{ '0': 'Red', '1': 'Green', Red: 0, Green: 1, Blue: 'blur' }
五、交叉类型
交叉类型是将多个类型合并为一个类型
。它包含了所需的所有类型的特性,使用&定义交叉类型
。
{type Useless = string & number;
}
如果我们仅仅把原始类型、字面量类型、函数类型等原子类型合并成交叉类型,是没有任何意义的。在上述的代码中,类型别名 Useless 的类型就是个 never。
交叉类型真正的用处是将多个接口类型合并成一个类型,从而实现等同接口继承的效果
,也就是所谓的合并接口类型,如下代码所示:
type IntersectionType = { id: number; name: string; } & { age: number };
const mixed: IntersectionType = {id: 1,name: 'name',age: 18}
在上述示例中,我们通过交叉类型,使得 IntersectionType 同时拥有了 id、name、age 所有属性,这里我们可以试着将合并接口类型理解为求并集。
相关文章:
Typescript基础知识(类型断言、类型别名、字符串字面量类型、枚举、交叉类型)
系列文章目录 引入一:Typescript基础引入(基础类型、元组、枚举) 引入二:Typescript面向对象引入(接口、类、多态、重写、抽象类、访问修饰符) 第一章:Typescript基础知识(Typescri…...
Windows系统扩充C盘空间系列方法总结
目录前言方法一 使用自带的Windows的DiskPart扩充C盘1. 打开cmd2.三步命令方法二:使用Windows系统内置磁盘管理扩展C盘方法三. 使用专业磁盘分区工具总结前言 本教程是总结Windows系统进行C盘(系统盘)扩充空间的系列方法,一般来讲…...
华为OD机试 - 跳格子(Python)
跳格子 题目 地上共有N个格子,你需要跳完地上所有的格子, 但是格子间是有强依赖关系的,跳完前一个格子后, 后续的格子才会被开启,格子间的依赖关系由多组steps数组给出, steps[0]表示前一个格子,steps[1]表示steps[0]可以开启的格子: 比如[0,1]表示从跳完第0个格子以后…...
Java配置文件的值注入
1.平常使用直接在变量头上加上Value就可以把配置文件的值注入进来 Value(“${environment.active}”) private String environment; 2.但是变量使用static修饰时,就不能注入进来了 Value(“${environment.active}”) private static String environment; 这是因…...
SAP 订单BOM与销售BOM的区别
订单BOM与销售BOM的区别 訂單BOM: 是實際生產時用的BOM, 在標準BOM和銷售BOM基礎上增減物料的BOM 銷售BOM: 是為特定客戶設定的BOM, 在主檔數據層次上的BOM, 在生產時是帶到訂單BOM中去的. 標準BOM: 是公司為標準生產的BOM, 在主檔數據層次上的BOM, 在生產時是帶到訂單BOM中去的…...
支付宝支付详细流程
1、二维码的生成二维码生成坐标 <!-- zxing生成二维码 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.3.3</version></dependency><dependency><groupId>co…...
TCP 的演化史-fast retransmit/recovery
工作原因要对一个 newreno 实现增加 sack 支持。尝试写了 3 天 C,同时一遍又一遍梳理 sack 标准演进。这些东西我早就了解,但涉及落地写实现,就得不断抠细节,试图写一个完备的实现。 这事有更简单的方法。根本没必要完全实现 RFC…...
CSS基础选择器,你认识多少?
前言在上一文初识CSS中,我们了解到了其格式:选择器{ }在初步尝试使用时,我们笼统的直接输入了p { }以选择p标签来对其操作,而这一章节里,我们再进一步探索有关基础选择器的相关内容,理解选择器的作用。选择…...
ChatGPT入门案例|商务智能对话客服(三)
本篇介绍智能客服的基本功能架构和基本概念,并利用对话流技术构建商务智能应用。 01、商务智能客服功能结构 互联网的发展已经深入到社会的各个方面,智能化发展已经成为社会发展的大趋势。在大数据和互联网时代,企业和组织愈加重视客户沟通…...
Matlab 最小二乘法拟合平面(SVD)
文章目录 一、简介1.1最小二乘法拟合平面1.2 SVD角度二、实现代码三、实现效果参考资料一、简介 1.1最小二乘法拟合平面 之前我们使用过最为经典的方式对平面进行了最小二乘拟合(点云最小二乘法拟合平面),其推导过程如下所示: 仔细观察一下可以发现...
AtCoder Regular Contest 126 D题题解
思路 首先我们看看假设选中 mmm 个数后的答案。 我们首先现将 mmm 个数移动到一起,在将他们重新排序。 我们知道,mmm 个数移在一起时,当位于中间的那个数不动时交换次数最少,于是可以列出式子(cic_ici 是点 iii 的…...
Android R WiFi热点流程浅析
Android R WiFi热点流程浅析 Android上的WiFi SoftAp功能是用户常用的功能之一,它能让我们分享手机的网络给其他设备使用。 那Android系统是如何实现SoftAp的呢,这里在FWK层面做一个简要的流程分析,供自己记录和大家参考。 以Android R版本为…...
【C++进阶】二、多态详解(总)
目录 一、多态的概念 二、多态的定义及实现 2.1 多态的构成条件 2.2 虚函数 2.3 虚函数的重写 2.4 虚函数重写的两个例外 2.4.1 协变 2.4.2 析构函数的重写 2.5 C11 override 和 final 2.5.1 final 2.5.2 override 2.6 重载、覆盖(重写)、隐藏(重定义)的对比 三、…...
node-sass@4.14.1 包含风险, 如何升级依赖至 dart-sass
文章目录需求我上网都查到了哪些信息在 github 看到了 node-sass 依赖的最新版本的列表:关于方案2的失败不同版本的 nodejs 和 node-sass依赖的**适配关系**从何得知替代方案——dart-sass如何安装 dart sass?需求 在做一个基于Node、React的前端项目&a…...
DataWhale 大数据处理技术组队学习task2
三、Hadoop分布式文件系统 1. 产生背景 数据量越来越大,一台独立的计算机已经无法存储所有的数据---->将大规模的数据存储到成百上千的计算机中------为了解决数据管理以及维护极其繁琐与低效------>分布式文件系统 分布式文件系统是管理网络中跨多台计算机…...
一文读懂select、poll、epoll的用法
select,poll,epoll都是IO多路复用的机制。I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,…...
《C陷阱与缺陷》----词法“陷阱”
导言: 由于一个程序错误可以从不同层面采用不同方式进行考察,而根据程序错误与考察程序的方式之间的相关性,可以将程序错误进行划分为各种陷阱与缺陷: ①.词法“陷阱” ②.语法“陷阱” ③.语义“陷阱” ④.连接问题 ⑤.库函数问…...
千锋教育+计算机四级网络-计算机网络学习-04
UDP概述 UDP协议 面向无连接的用户数据报协议,在传输数据前不需要先建立连接;目地主机的运输层收到UDP报文后,不需要给出任何确认 UDP特点 相比TCP速度稍快些简单的请求/应答应用程序可以使用UDP对于海量数据传输不应该使用UDP广播和多播应用…...
蓝桥杯算法训练合集十四 1.P08052.P07053.同余方程4.P08015.ascii应用
目录 1.P0805 2.P0705 3.同余方程 4.P0801 5.ascii应用 1.P0805 问题描述 当两个比较大的整数相乘时,可能会出现数据溢出的情形。为避免溢出,可以采用字符串的方法来实现两个大数之间的乘法。具体来说,首先以字符串的形式输入两个整数&…...
判断字符串中的字符的类型isdecimal();isalpha();isdigit();isalnum()
【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 判断字符串中的字符的类型 isdecimal();isalpha();isdigit();isalnum() [太阳]选择题 对于代码中isdecimal()和isalnum()输出的结果是? s "ABc123&…...
VSCode远程调试Linux代码,python解释器配置
安装插件并配置 安装后找到插件图标,点击 点击SSH上的 号 在弹出框中输入命令:ssh usernameip -p port username: 远程服务器的用户名 ip: 远程ip port:端口号,没有可以不用 输入完毕后点击enter 选择ssh配置文件保存…...
03:入门篇 - CTK Plugin Framework 基本原理
作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 CTK Plugin Framework 技术是面向 C++ 的动态模型系统。该系统允许插件之间的松散耦合,并且提供了设计良好的方式来进行功能和数据的交互。此外,它没有预先对插件施加限制,这样就可以很容易地将插件的相关…...
面试攻略,Java 基础面试 100 问(九)
数组有没有 length()方法?String 有没有 length()方法? 数组没有 length()方法,有 length 的属性。String 有 length()方法。JavaScript 中,获得字符串的长度是通过 length 属性得到的,这一点容易和 Java混淆。 在 Java 中&…...
JavaScript 代码不嵌套主义
文章目录前言一、何为嵌套代码二、避免嵌套1.提炼抽取2.反转排列总结前言 看过不少过度嵌套的代码, 我真正意识到问题的严重性是刚入职那会, 我在一个老项目里看到了40个连续的else if, 套了6层的if, for和forEach, 因为我们并没有做什么限制代码嵌套的提前约定. 呃, 那之后认…...
使用默认参数的4大要点
概述 默认参数是C中新增的特性。在C中,可以为函数的参数指定默认值。调用函数时,如果没有指定实参,则自动使用默认参数。默认参数的基本语法这里就不作介绍了,下面重点介绍使用默认参数的一些知识要点。 基本规则 1、当函数中某个…...
Linux文件系统中的硬链接及常见面试题
如果能对inode的概念有所了解,对理解本文会有所帮助。如果对inode的概念不太清楚也没有关系,我们会捎带介绍一下。在文件系统的实现层面,我们可以认为包含两个组件:一个是包含数据块的池子,池子中的数据块是等大小的&a…...
opencv-StereoBM算法
原理解释目前立体匹配算法是计算机视觉中的一个难点和热点,算法很多,但是一般的步骤是:A、匹配代价计算匹配代价计算是整个立体匹配算法的基础,实际是对不同视差下进行灰度相似性测量。常见的方法有灰度差的平方SD(squ…...
图像分类竞赛进阶技能:OpenAI-CLIP使用范例
OpenAI-CLIP 官方介绍 尽管深度学习已经彻底改变了计算机视觉,但目前的方法存在几个主要问题:典型的视觉数据集是劳动密集型的,创建成本高,同时只教授一组狭窄的视觉概念;标准视觉模型擅长于一项任务且仅擅长于一项任务,并且需要大…...
Metasploit框架基础(一)
文章目录前言一、基础认知二、批量POC/EXP的构想三、poc检测框架的简单实现四、xray五、Meatsploit框架参考前言 Metasploit 一款渗透测试框架漏洞利用的集合与构建和定制满足你的需求的基础漏洞利用和验证的工具 这几个说法都是百度或者官方文档中出现的手法,说…...
pytorch零基础实现语义分割项目(二)——标签转换与数据加载
数据转换与加载项目列表前言标签转换RGB标签到类别标签映射RGB标签转换成类别标签数据数据加载随机裁剪数据加载项目列表 语义分割项目(一)——数据概况及预处理 语义分割项目(二)——标签转换与数据加载 语义分割项目&#x…...
邯郸质量一站式服务平台上线/班级优化大师是干什么用的
基础标签##H标签:作用: 用于给文本添加标题语义格式:xxxxxx注意点: H标签是用来给文本添加标题语义的, 而不是用来修改文本的样式的H标签一共有6个, 从H1~H6, 最多就只能到6, 超过6则无效在浏览器中会独占一行在H系列的标签中, H1最大, H6最小。在企业开发中, 一定要…...
企业建设好一个网站后 如何进行网站推广/免费seo网站优化
在PHP中使用Sentry非常简单。安装库后,您可以直接与客户端连接并开始提交数据。 一、基本 最重要的部分是创建raven客户端。创建一次,并从想要与Sentry接口的任何地方引用它: $sentryClient new Raven_Client(https://<key>sentry.…...
建设银行 网站设置密码/合肥seo报价
1. 水平居中设置-行内元素 我们在实际工作中常会遇到需要设置水平居中的场景,比如为了美观,文章的标题一般都是水平居中显示的。 这里我们又得分两种情况:行内元素还是 块状元素,块状元素里面又分为定宽块状元素,以及…...
做网站有什么用出/全媒体广告投放平台
第一步:建立数据库(这部分已经在《关于oracle中自增字段问题总结》一文中写过。点此查看第二步:创建一个查询过程,因为在登录时要根据用户名查询用户密码此步要用到pl/sql编程知识,代码如下:create or replace procedu…...
wordpress做产品页教程/网络推广网站电话
注:如果没有 root 权限也是可以试试,一般情况下,都需要 root 权限,才能连接成功。1.需要确保你的开发 PC 和 Android 手机都连上了 wifi 并处于同一网段下;2.开启 usb 调试,且用 usb 将 Android 设备连接到…...
淘宝客做网站要钱吗/网络运营是什么意思
https://jingyan.baidu.com/article/fea4511a1a1040f7bb91251a.html转载于:https://www.cnblogs.com/clover-xuqi/p/8316663.html...