TypeScript——类型系统与类型推导

news2025/1/11 0:30:27

前言

TypeScript 是由 Microsoft 开发的一种开放源代码语言。 它是 JavaScript 的一个超集,这意味着你可以在 TypeScript 中使用 JS 已存在的所有语法,并且所有 JavaScript 脚本都可以当作 TypeScript 脚本,此外它还增加了一些自己的语法。TypeScript 对 JavaScript 添加的最的核心功能,就是它的类型系统。

1. 类型系统

在 TypeScript 中,可以使用类型提示来识别变量或参数的数据类型。 使用类型提示,可以描述对象的形状,这样不仅可以提供更好的文档,还能使 TypeScript 能够更好的验证代码是否正常工作。

通过静态类型检查,TypeScript 在开发初期就能发现代码问题,而 JavaScript 往往只能够在浏览器中运行时才会发现。 类型还让你可以描述代码的用途, 如果你是在团队中工作,那么在多人协作开发时也能更简单、高效。

类型还可以为开发工具提供各种便捷和生产力优势,例如 IntelliSense(智能感知)、基于符号的导航、转到定义、查找所有引用、语句结束和代码重构。

2. 类型声明

基本类型声明

TypeScript 代码最明显的特征,就是为 JavaScript 变量加上了类型声明。

let foo: string

上面示例中,变量 foo 的后面使用冒号,声明了它的类型为 string

类型声明的写法,一律为在标识符后面添加 “冒号 + 类型” 。函数参数和返回值,也是这样来声明类型,下面是 TypeScript 中常用的声明类型的方式:

let foo: string

let age: number

let bar: boolean

let b: null

let c: undefined

let d: bigint

let e: symbol

function getVal(val: string): string {
    return val
}

同样的它们只能被赋值为该类型的值:

foo = '123'

age = 123

bar = true

b = null

c = undefined

d = 123456n

e = Symbol()

object 类型

根据 Javascript 的设计,object 可以作为所有对象、数组和函数的类型:

let a: object

a = {}
a = []
a = () => {}

上面示例中,对象、数组、函数都属于 object 类型。虽然 TypeScript 这样的行为比较贴合 JavaScript 作为弱类型语言的表现形式,但是在实际开发应用中却很少使用 object 作为以上三者的类型声明。对象、数组、函数的类型都有更为具体、规范的定义方式:

interface Person {
    name: string
}

type Fn = (args: any) => void

let a: Person

let b: any[]

let c: Fn

以上分别列举了最常见的用法,定义了对象、数组、函数的类型。而 interfacetype 的强大之处绝不仅仅于此,在后续的篇幅中我们会详细讲解这两个类型。

undefined 和 null 类型

值得注意的是,undefinednull 是所有类型的子类型,在非严格模式下undefinednull 这两种类型的变量可以赋值给其他类型,如下:
在这里插入图片描述

然而在严格模式下,上述的写法就会报错:

在这里插入图片描述

这里推荐开启 "strict": true 直接启用严格模式开发,可以更严格地检测类型错误,以减少错误的发生。

3. interface「接口」

interface “接口”,我们前端很熟悉的就是跟后端同学一起联调接口,但却不能和 TypeScript 中的 “接口” 混为一谈。

在面向对象语言中,接口(Interfaces)是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类(classes)去实现(implement)。

如何描述对象的形状

TypeScript 中的接口是一个非常灵活的概念,除了可用于 对类的一部分行为进行抽象 以外,也常用于描述对象的形状

interface Person {
    name: string
    age: number
}

let p: Person

p = {
    name: '',
    age: 18
}

上述的代码就是 interface 的一个基本用法。我们都知道,在 JavaScript 中对象是可以随意的增加、删除、修改属性的,这样具备极大的灵活性,却也可能带来一定的开发风险。

而 TypeScript 只关心我们赋值给变量的 “值的结构”,它只关心它是否具有预期的属性。 只关心类型的结构和功能,这就是为什么 TypeScript 常常被称之为是一个 结构化类型 的类型系统。当编写以下代码后,TypeScript 会及时给出报错:

p.age = ''
// TS2322: Type  string  is not assignable to type  number 

p.gender = 'male'
// TS2339: Property  gender  does not exist on type  Person 

delete p.name
// TS2790: The operand of a  delete  operator must be optional.

灵活的 interface

那么可能有的同学可能就有疑惑了,我就是要这样写代码,TypeScript 这么不灵活,老子 TM 不学了 😡😡😡。其实不然,通过下述写法在保留可维护性、安全性的同时还能具备一定的灵活性:

interface Person {
    name?: string // 可选属性
    age: number | string // 联合类型
    [p: string]: any; // 任意属性
}

let p: Person

p = {
    name: '',
    age: 18
}

p.age = ''

p.gender = 'male'

delete p.name

我们可以在属性名后面加一个 ? 标记表示这个属性是可选的。这样在 初始化对象的时候 就可以根据需要选择是否添加某个属性,并且在后续操作中也可以 选择删除或增加 这个属性。

通过任意属性,我们可以很灵活的给一个对象扩展新的属性。在某些时候,对象属性值的类型可能会有多种,我们则可以用 联合类型 来定义。

4. type「类型别名」

我们已经学会在类型注解里直接使用对象类型和联合类型,这很方便,但有的时候,一个类型会被使用多次,此时我们更希望通过一个单独的名字来引用它。

这就是类型别名(type alias)。所谓类型别名,顾名思义,一个可以指代任意类型的名字。类型别名的语法:

type Name = string;

type NameResolver = () => string;

type NameOrResolver = Name | NameResolver;

function getName(n: NameOrResolver): Name {
    if (typeof n === 'string') {
        return n;
    } else {
        return n();
    }
}

也能用来定义对象和联合类型:

type Age = number

type Name = string

type Person = {
    name: Name
    age: Age
}

type Foo = Age | Name

跟定义 interface 很类似,将上述的示例代码改改就行:

type Age = number | string

type Person = {
    name?: string // 可选属性
    age: Age // 联合类型
    [p: string]: any; // 任意属性
}

let p: Person

p = {
    name: '',
    age: 18
}

p.age = ''

p.gender = 'male'

delete p.name

以上的代码可以直接运行,也是没有任何问题的。

5. typeof

JavaScript 中有一个操作符 typeof 可以用来获取一个值的类型,但是我们可能某些时候不会使用它,因为它不能准确分辨出对象和数组。在 TypeScript 中有一个同样的类型操作符 typeof ,它可以用来获取一个值 TS 类型,代码如下:

const info = {
    name: 'John',
}

const list = [1, 2, 3]

type Info = typeof info

type List = typeof list

类型 Info 此时等同于 {name: string}List 等同于 number[],我们来试一试加在变量上的表现:

在这里插入图片描述

通过使用 typeof 操作符可以获取任意值的 TS 类型,当某个复杂的对象已经写好了而我们又不太想手写它的类型时,typeof 就变得尤为有用:

const person = {
    name: 'lison',
    age: 18,
    id: 1,
    school: '清华大学',
    address: '北京市',
    birthday: '2001-01-01',
    height: 170,
    weight: 120,
    hobby: ['sleep', 'eat', 'run'],
    score: {
        math: 100,
        chinese: 90,
        english: 80
    }
}

function printPerson(p: typeof person) {
    console.log(p.name)
}

还有一个需要注意的点是,在 TypeScript 中,const 声明的变量具有字面量类型(literal types)。字面量类型是一种特殊的类型,用于表示一个固定的、不可变的值。这些类型包括字符串、数字、布尔值、对象、数组和元组等。当你使用 const 声明一个变量并给它赋一个具体的值时,TypeScript 会推断该变量的类型为字面量类型。例如:

const pi = 3.14159

type PI = typeof pi // 3.14159

当类型 PI 被作为某个变量的类型时,它就只能被赋值为 3.14159,否则就会报错:
在这里插入图片描述

6. 类型推导

如果没有明确的指定类型,那么 TypeScript 会依照类型推导(Type Inference)的规则推导出一个类型。

什么是类型推导

以下代码虽然没有指定类型,但是会在编译的时候报错:

let myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.

事实上,它等价于:

let myFavoriteNumber: string = 'seven';
myFavoriteNumber = 7;

// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.

TypeScript 会在没有明确的指定类型的时候会通过解析代码推测出一个类型,这就是类型推导。正因为有这样的功能,在日常开发中,对于一些简单的、不会更改的数据我们可以不用显式去定义类型。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何为短信营销制定最佳策略

营销是一个永无止境的过程,不断寻找新的和创新的方式来吸引更多客户或与他们沟通。短信于1992年首次发出,现在已经31岁了。这可能看起来有点老派,但你会惊讶于这项技术是如何卷土重来的,特别是对于小企业。打开率为98%&#xff0c…

STM32输出3对PWM互补信号做电机控制-C代码

1、使用芯片STM32F103VC 2、打开MXCube新建工程 3、配置下载模式为SW,外部晶振8M,主频72M 4、配置高级定时器1,使用内部晶振,开启互补PWM输出模式 5、配置载波频率10k,即周期为10us (定时周期 (Prescal…

c语言实现栈

文章目录 前言一、栈的特征二、栈的实现1、栈的设计2、栈的初始化和销毁3、元素的入栈和出栈4、返回栈顶元素 三、栈的应用 前言 在学习完链表之后,接下来就要了解另外的两个常用的线性数据结构,栈和队列。 一、栈的特征 栈:一种特殊的线性…

斩获多家名校邀请函|检验医师终赴多伦多大学访学深造

M医生学术背景不错,具备较扎实的基础医学理论及较熟练的实验技能,也有一定的英语能力,但因本身不够自信,担心申请不到名校通不过CSC审批。我们先后为其获得新加坡科技研究局(A*Star)、加拿大麦吉尔大学、多…

为什么企业需要IT服务管理?

什么是IT服务管理? 将IT服务管理功能扩展到技术服务之外,解决以业务为中心通过单一平台,门户和服务目录管理服务供需,通过PaaS/低代码开发工具加速创新和工作流自动化。 为什么企业需要IT服务管理? 为了更好管理公司内不同业务&a…

功能强大、超低功耗的STM32WL55JCI7、STM32WL55CCU7、STM32WL55CCU6 32位无线远距离MCU

STM32WL55xx 32位无线远距离MCU嵌入了功能强大、超低功耗、符合LPWAN标准的无线电解决方案,可提供LoRa、(G)FSK、(G)MSK和BPSK等各种调制。STM32WL55xx无线MCU的功耗超低,基于高性能Arm Cortex-M4 32位RISC内核(工作频率高达48MHz&#xff09…

优化ADC 采样计算的简单思路

想法是尽量简化ADC 采样值换算到真实电压的过程,最好是不涉及浮点运算,整数乘除法成本比较低。 原理 对于使用了分压电阻采样输入电压的情形,电路大概是这样: 分压比例为: K R 1 R 2 R 1 (1) K \frac{R1 R2}{R1}…

java 实现N次多项式回归

使用的类库 org.apache.commons.math3 maven <dependency><groupId>org.apache.commons</groupId><artifactId>commons-math3</artifactId><version>3.6.1</version> </dependency> 推荐工具 如果只是做学术研究用&…

摩托车外廓尺寸检测软件

本系统为摩托车外廓尺寸检测软件&#xff0c;该系统共涉及两种测量方法&#xff1a;自动测量和手动测量&#xff0c;旨在测量出每一台摩托车的外廓尺寸&#xff0c;包括但不限于摩托车的车长、车宽、车高、轮距、前悬、后悬、前伸距等需要测量的参数&#xff0c;可通过运行软件…

ATFX汇市:美元指数强势状态延续,市价逼近104关口

环球汇市行情摘要—— 昨日&#xff0c;美元指数上涨0.27%&#xff0c;收盘在103.61点&#xff0c; 欧元贬值0.48%&#xff0c;收盘价1.0846点&#xff1b; 日元贬值0.24%&#xff0c;收盘价145.87点&#xff1b; 英镑贬值0.19%&#xff0c;收盘价1.2733点&#xff1b; 瑞…

Vulnhub: bassamCTF: 1靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.210 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.210 修改hosts文件 爆破出子域名welcome wfuzz -H HOST: FUZZ.bassam.ctf -u http://192.168.111.210 -w /usr/share/wor…

GB28181视频监控国标平台EasyGBS角色绑定设备通道的功能优化

GB28181视频监控国标平台EasyGBS是基于国标GB28181协议、支持多路设备同时接入的视频监控/视频云服务平台&#xff0c;支持对多平台、多终端分发RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。国标GB28181平台EasyGBS可提供视频直播监控、云端录像、云存储、检索回放、智能告警…

电子器件系列47:稳压二极管

C80857_稳压二极管_BZX84C15LT1G_规格书_ONSEMI(安森美)稳压二极管规格书 232-稳压二极管的串联使用&#xff0c;和普通二极管串联也能灵活稳压_哔哩哔哩_bilibili 基本释义    稳压二极管&#xff0c;英文名称Zener diode&#xff0c;又叫齐纳二极管。    利用pn结反向击穿…

IPv6 基础概念

IPv6 基础概念 组播地址 IPv6的组播与IPv4相同&#xff0c;用来标识一组接口&#xff0c;一般这些接口属于不同的节点。一个节点可能属于0到多个组播组。发往组播地址的报文被组播地址标识的所有接口接收。例如组播地址FF02::1表示链路本地范围的所有节点&#xff0c;组播地址…

什么是3D智慧档案馆?智慧档案馆如何建设?

档案馆3D可视化解决方案 一、引言 随着科技的飞速发展和数字化转型的推进&#xff0c;档案馆作为文化遗产和重要信息的保管者&#xff0c;面临着新的挑战和机遇。为了更好地保护和管理档案资料&#xff0c;提高档案馆的管理效率和透明度&#xff0c;我们提出了一种档案馆3D可视…

代驾系统:革新出行体验的智能伙伴

在现代社会&#xff0c;出行方式正在经历着一场革命&#xff0c;而代驾系统正是这场革命中的一位智能伙伴。通过结合智能科技和出行需求&#xff0c;代驾系统为我们带来了便捷、安全、个性化的出行体验。本文将介绍代驾系统的工作原理&#xff0c;并通过Python代码演示其基本功…

ChatGLM-Med,HuaTuo,ChatDoctor

ChatGLM-Med&#xff1a;基于中文医学知识的ChatGLM模型微调 HuaTuo&#xff1a;基于中文医学知识的LLaMA微调模型 ChatDoctor&#xff1a;基于常见医疗数据微调的LLaMA 目录 ChatGLM-MedHuaTuoChatDoctor ChatGLM-Med 模型为ChatGLM-6B&#xff0c;微调数据集为&#xff1a;医…

uniapp使用uni.chooseLocation()打开地图选择位置

使用uni.chooseLocation()打开地址选择位置&#xff1a; 在Uniapp源码视图进行设置 添加这个属性&#xff1a;"requiredPrivateInfos":["chooseLocation"] ​ </template><view class"location_box"><view class"locatio…

repair taillights

自己修理汽车尾灯&#xff0c;可以根据型号去某宝买个回来自己安装&#xff1a;

【前端从0开始】JavaSript——js基础语法

1. JS基础语法 1.1. JS概念 JavaScript 是用于实现用户交互、动态控制文档的外观和内容, 动态控制浏览器操作、创建cookies等网页行为的跨平台、跨浏览器的由浏览器解释执行的客户端脚本语言。 js文档 1.2. 特点 是基于对象的弱类型语言 弱类型语言: 某一个变量被定义类型…