#Ts篇: ts学习再梳理

ts类型梳理

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

function toString(num: number): string {return String(num);
}

上面示例中,函数toString()的参数num的类型是number。参数列表的圆括号后面,声明了返回值的类型是string。

值代码和类型代码

TypeScript 代码只涉及类型,不涉及值。所有跟“值”相关的处理,都由 JavaScript 完成。

运行环境网址

https://www.typescriptlang.org/play/?#code/PTAEHUFMBsGMHsC2lQBd5oBYoCoE8AHSAZVgCcBLA1UABWgEM8BzM+AVwDsATAGiwoBnUENANQAd0gAjQRVSQAUCEmYKsTKGYUAbpGF4OY0BoadYKdJMoL+gzAzIoz3UNEiPOofEVKVqAHSKymAAmkYI7NCuqGqcANag8ABmIjQUXrFOKBJMggBcISGgoAC0oACCbvCwDKgU8JkY7p7ehCTkVDQS2E6gnPCxGcwmZqDSTgzxxWWVoASMFmgYkAAeRJTInN3ymj4d-jSCeNsMq-wuoPaOltigAKoASgAywhK7SbGQZIIz5VWCFzSeCrZagNYbChbHaxUDcCjJZLfSDbExIAgUdxkUBIursJzCFJtXydajBBCcQQ0MwAUVWDEQC0gADVHBQGNJ3KAALygABEAAkYNAMOB4GRonzFBTBPB3AERcwABS0+mM9ysygc9wASmCKhwzQ8ZC8iHFzmB7BoXzcZmY7AYzEg-Fg0HUiQ58D0Ii8fLpDKZgj5SWxfPADlQAHJhAA5SASPlBFQAeS+ZHegmdWkgR1QjgUrmkeFATjNOmGWH0KAQiGhwkuNok4uiIgMHGxCyYrA4PCCJSAA

any

1.使用场景,某些需要关闭验证
2.为了适配老的js项目
只要开发者使用了any类型,就表示开发者想要自己来处理这些代码,所以就不对any类型进行任何限制,怎么使用都可以。

从集合论的角度看,any类型可以看成是所有其他类型的全集,包含了一切可能的类型。
TypeScript 将这种类型称为“顶层类型”(top type),意为涵盖了所有下层。

缺点
any类型除了关闭类型检查,还有一个很大的问题,就是它会“污染”其他变量。

let x: any = "hello";
let y: number;y = x; // 不报错y * 123; // 不报错
y.toFixed(); // 不报错

unknown

为了解决any类型“污染”其他变量的问题
它与any含义相同,表示类型不确定,可能是任意类型,但是它的使用有一些限制,不像any那样自由,可以视为严格版的any。

首先,unknown类型的变量,不能直接赋值给其他类型的变量(除了any类型和unknown类型)。

let v: unknown = 123;let v1: boolean = v; // 报错
let v2: number = v; // 报错

其次,不能直接调用unknown类型变量的方法和属性。

let v1: unknown = { foo: 123 };
v1.foo; // 报错let v2: unknown = "hello";
v2.trim(); // 报错let v3: unknown = (n = 0) => n + 1;
v3(); // 报错

再次,unknown类型变量能够进行的运算是有限的,只能进行比较运算(运算符==、=、!=、!、||、&&、?)、取反运算(运算符!)、typeof运算符和instanceof运算符这几种,其他运算都会报错。

答案是只有经过“类型缩小”,unknown类型变量才可以使用。所谓“类型缩小”,就是缩小unknown变量的类型范围,确保不会出错

never

ypeScript 还引入了“空类型”的概念,即该类型为空,不包含任何值。
由于不存在任何属于“空类型”的值,所以该类型被称为never,即不可能有这样的值。
使用场景
1 主要是在一些类型运算之中,保证类型运算的完整性
2 不可能返回值的函数,返回值的类型就可以写成never
3 如果一个变量可能有多种类型(即联合类型),通常需要使用分支处理每一种类型。这时,处理所有可能的类型之后,剩余的情况就属于never类型。

function fn(x: string | number) {if (typeof x === "string") {// ...} else if (typeof x === "number") {// ...} else {x; // never 类型}
}

never类型的一个重要特点是,可以赋值给任意其他类型。

为什么never类型可以赋值给任意其他类型呢?这也跟集合论有关,空集是任何集合的子集。TypeScript 就相应规定,任何类型都包含了never类型。因此,never类型是任何其他类型所共有的,TypeScript 把这种情况称为“底层类型”(bottom type)。

总之,TypeScript 有两个“顶层类型”(any和unknown),但是“底层类型”只有never唯一一个。

包装对象类型与字面量类型

"hello"; // 字面量
new String("hello"); // 包装对象

了区分这两种情况,TypeScript 对五种原始类型分别提供了大写和小写两种类型。
Boolean 和 boolean
String 和 string
Number 和 number
BigInt 和 bigint
Symbol 和 symbol

const s1: String = "hello"; // 正确
const s2: String = new String("hello"); // 正确const s3: string = "hello"; // 正确
const s4: string = new String("hello"); // 报错

建议只使用小写类型,不使用大写类型。因为绝大部分使用原始类型的场合,都是使用字面量,不使用包装对象

Object 类型与 object 类型

大写的Object类型代表 JavaScript 语言里面的广义对象。所有可以转成对象的值,都是Object类型,这囊括了几乎所有的值。

let obj: Object;obj = true;
obj = "hi";
obj = 1;
obj = { foo: 123 };
obj = [1, 2];
obj = (a: number) => a + 1;

上面示例中,原始类型值、对象、数组、函数都是合法的Object类型。

小写的object类型代表 JavaScript 里面的狭义对象,即可以用字面量表示的对象,只包含对象、数组和函数,不包括原始类型的值。

let obj: object;obj = { foo: 123 };
obj = [1, 2];
obj = (a: number) => a + 1;
obj = true; // 报错
obj = "hi"; // 报错
obj = 1; // 报错

值类型

let x: 5 = 5;
let y: number = 4 + 1;x = y; // 报错
y = x; // 正确

联合类型 |

联合类型A|B表示,任何一个类型只要属于A或B,就属于联合类型A|B

let x: string | number;
x = 123; // 正确
x = "abc"; // 正确

交叉类型

指的多个类型组成的一个新类型,使用符号&表示。

let obj: { foo: string } & { bar: string };obj = {foo: "hello",bar: "world",
};

上面示例中,变量obj同时具有属性foo和属性bar

type类型

type命令用来定义一个类型的别名。

type Age = number;let age: Age = 55;

上面示例中,type命令为number类型定义了一个别名Age。这样就能像使用number一样,使用Age作为类型

typeof

console.log(typeof undefined); // "undefined"
console.log(typeof 0);         // "number"
console.log(typeof 123);       // "number"
console.log(typeof -1.5);      // "number"
console.log(typeof NaN);       // "number" (注意:尽管 NaN 表示“不是数字”,但其类型仍然是 number)
console.log(typeof true);      // "boolean"
console.log(typeof false);     // "boolean"
console.log(typeof "");        // "string"
console.log(typeof "hello");   // "string"
console.log(typeof [1, 2, 3]); // "object" (数组被视为对象)
console.log(typeof {a: 1});    // "object"
console.log(typeof null);      // "object" (这是一个历史遗留问题,null 实际上表示空值)
console.log(typeof function(){}); // "function"
console.log(typeof class {});  // "function" (类也是函数的一种形式)

另外,typeof命令的参数不能是类型

块级类型声明

if (true) {type T = number;let v: T = 5;
} else {type T = string;let v: T = "hello";
}

上面示例中,存在两个代码块,其中分别有一个类型T的声明。这两个声明都只在自己的代码块内部有效,在代码块外部无效。

类型的兼容

type T = number | string;let a: number = 1;
let b: T = a;

上面示例中,变量a和b的类型是不一样的,但是变量a赋值给变量b并不会报错。这时,我们就认为,b的类型兼容a的类型。

数组的类型

1 数组的类型有两种写法。

let arr: number[] = [1, 2, 3];

如果数组成员的类型比较复杂,可以写在圆括号里面

let arr: (number | string)[];

2 数组类型的第二种写法是使用 TypeScript 内置的 Array 接口。

let arr: Array<number> = [1, 2, 3];
只读数组,const 断言

TypeScript 允许声明只读数组,方法是在数组类型前面加上readonly关键字。

const arr: readonly number[] = [0, 1];arr[1] = 2; // 报错
arr.push(3); // 报错
delete arr[0]; // 报错

Index signature in type ‘readonly number[]’ only permits reading.
Property ‘push’ does not exist on type ‘readonly number[]’.
Index signature in type ‘readonly number[]’ only permits reading.

元组

元组(tuple)是 TypeScript 特有的数据类型,

JavaScript 没有单独区分这种类型。

它表示成员类型可以自由设置的数组,即数组的各个成员的类型可以不同。

元组必须明确声明每个成员的类型。

const s: [string, string, boolean] = ["a", "b", true];

元组类型的写法,与上一章的数组有一个重大差异

数组的成员类型写在方括号外面(number[]),

元组的成员类型是写在方括号里面([number])。

TypeScript 的区分方法是,成员类型写在方括号里面的就是元组,写在外面的就是数组

let a: [number] = [1];

上面示例中,变量a是一个元组,只有一个成员,类型是number。


元组成员的类型可以添加问号后缀(?),表示该成员是可选的

let a: [number, number?] = [1];

symbol类型

函数的类型

function hello(txt: string): void {console.log("hello " + txt);
}

,函数hello()在声明时,需要给出参数txt的类型(string),以及返回值的类型(void),后者写在参数列表的圆括号后面。void类型表示没有返回值。


函数返回 void 类型

代表函数没有返回值

function f(): void {return 123; // 报错
}

如果返回其他值,就会报错。

函数返回 never类型

// 正确
function sing(): void {console.log("sing");
}// 报错
function sing(): never {console.log("sing");
}

上面示例中,函数sing()虽然没有return语句,但实际上是省略了return undefined这行语句,真实的返回值是undefined。所以,它的返回值类型要写成void,而不是never,写成never会报错。

高阶函数

一个函数的返回值还是一个函数,那么前一个函数就称为高阶函数(higher-order function)

(someValue: number) => (multiplier: number) => someValue * multiplier;

函数重载

有些函数可以接受不同类型或不同个数的参数,并且根据参数的不同,会有不同的函数行为。这种根据参数类型不同,执行不同逻辑的行为,称为函数重载(function overload)。

reverse("abc"); // 'cba'
reverse([1, 2, 3]); // [3, 2, 1]

对象

一旦声明了类型,对象赋值时,就不能缺少指定的属性,也不能有多余的属性。

type MyObj = {x: number;y: number;
};const o1: MyObj = { x: 1 }; // 报错
const o2: MyObj = { x: 1, y: 1, z: 1 }; // 报错

上面示例中,变量o1缺少了属性y,变量o2多出了属性z,都会报错。

接口赋值类型
const {id,name,price,
}: {id: string;name: string;price: number;
} = product;
interface

interface 是对象的模板,可以看作是一种类型约定,中文译为“接口”。

使用了某个模板的对象,就拥有了指定的类型结构。

interface 继承 interface
interface Shape {name: string;
}interface Circle extends Shape {radius: number;
}
interface 继承 type
type Country = {name: string;capital: string;
};interface CountryWithPop extends Country {population: number;
}
接口合并
interface Box {height: number;width: number;
}interface Box {length: number;
}

两个Box接口会合并成一个接口,同时有height、width和length三个属性。

interface 与 type 的异同

interface命令与type命令作用类似,都可以表示对象类型。

很多对象类型即可以用 interface 表示,也可以用 type 表示。而且,两者往往可以换用,几乎所有的 interface 命令都可以改写为 type 命令。

  1. 它们的相似之处,首先表现在都能为对象类型起名。 —创造一个值,编译后依然存在。如果只是单纯想要一个类型,应该使用type或interface

interface 与 type 的区别有下面几点。

(1)type能够表示非对象类型,而interface只能表示对象类型(包括数组、函数等)。

(2)interface可以继承其他类型,type不支持继承。


继承的主要作用是添加属性,type定义的对象类型如果想要添加属性,只能使用&运算符,重新定义一个类型。

type Animal = {name: string;
};type Bear = Animal & {honey: boolean;
};

上面示例中,类型Bear在Animal的基础上添加了一个属性honey。

非空断言!

let value: string | null = "Hello";// 使用非空断言
let length = value!.length;console.log(length); // 输出:5

在这个例子中,value 的类型是 string | null,但在使用 value!.length 时,我们通过 ! 告诉编译器 value 不会是 null,因此可以直接访问其属性 length。

类的 interface 接口

implements 关键字
interface Country {name: string;capital: string;
}
// 或者
type Country = {name: string;capital: string;
};class MyCountry implements Country {name = "";capital = "";
}

interface或type都可以定义一个对象类型。

类MyCountry使用implements关键字,表示该类的实例对象满足这个外部类型。

可访问性修饰符

类的内部成员的外部可访问性,由三个可访问性修饰符(access modifiers)控制:

public、

private和protected。

public修饰符表示这是公开成员,外部可以自由访问

private修饰符表示私有成员,只能用在当前类的内部,类的实例和子类都不能使用该成员

protected修饰符表示该成员是保护成员,只能在类的内部使用该成员,实例无法使用该成员,但是子类内部可以使用。

静态成员

类的内部可以使用static关键字,定义静态成员。

静态成员是只能通过类本身使用的成员,不能通过实例对象使

泛型类
this 问题

泛型

函数返回值的类型与参数类型是相关的

function getFirst(arr) {return arr[0];
}

上面示例中,函数getFirst()总是返回参数数组的第一个成员。参数数组是什么类型,返回值就是什么类型。

函数的类型声明只能写成下面这样。

function f(arr: any[]): any {return arr[0];
}

为了解决这个问题,TypeScript 就引入了“泛型”(generics)。泛型的特点就是带有“类型参数”(type parameter)。

function getFirst<T>(arr: T[]): T {return arr[0];
}

上面示例中,函数getFirst()的函数名后面尖括号的部分,就是类型参数,参数要放在一对尖括号(<>)里面。本例只有一个类型参数T,可以将其理解为类型声明需要的变量,需要在调用时传入具体的参数类型。


接口的泛型写法

interface Box<Type> {contents: Type;
}let box: Box<string>;

Enum类型

as 类型断言

TypeScript 提供了“类型断言”这样一种手段,允许开发者在代码中“断言”某个值的类型,告诉编译器此处的值是什么类型。TypeScript 一旦发现存在类型断言,就不再对该值进行类型推断,而是直接采用断言给出的类型。

type T = "a" | "b" | "c";let foo = "a";
let bar: T = foo as T; // 正确

上面示例中,最后一行的foo as T表示告诉编译器,变量foo的类型断言为T,所以这一行不再需要类型推断了,编译器直接把foo的类型当作T,就不会报错了。

类型断言有两种语法。

// 语法一:<类型>值
value;

// 语法二:值 as 类型
value as Type;

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

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

相关文章

使用chrome 访问虚拟机Apache2 的默认页面,出现了ERR_ADDRESS_UNREACHABLE这个鸟问题

本地环境 主机MacOs Sequoia 15.1虚拟机Parallels Desktop 20 for Mac Pro Edition 版本 20.0.1 (55659)虚拟机-操作系统Ubuntu 22.04 服务器版本 最小安装 开发环境 编辑器编译器调试工具数据库http服务web开发防火墙Vim9Gcc13Gdb14Mysql8Apache2Php8.3Iptables 第一坑 数…

定时器的小应用

第一个项目 第一步&#xff0c;RCC开启时钟&#xff0c;这个基本上每个代码都是第一步&#xff0c;不用多想&#xff0c;在这里打开时钟后&#xff0c;定时器的基准时钟和整个外设的工作时钟就都会同时打开了 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);第二步&…

【工控】线扫相机小结 第三篇

海康软件更新 目前使用的是 MVS_STD_4.3.2_240705.exe &#xff0c;最新的已经到4.4了。 一个大的变动 在上一篇中我们提到一个问题&#xff1a; 需要注意的是&#xff0c;我们必须先设置 TriggerSelector 是 “FrameBurstStart” 还是 “LineStart” 再设置TriggerMode 是 …

零基础利用实战项目学会Pytorch

目录 pytorch简介 1.线性回归 2.数据类型 2.1数据类型检验 2.2Dimension0/Rank0 2.3 Dim1/Rank1 2.4 Dim2/Rank2 3.一些方法 4.Pytorch完成分类任务 4.1模型参数 4.2 前向传播 4.3训练以及验证 4.4 三行搞定&#xff01; 4.5 准确率 5、Pytorch完成回归任务 5.…

【#IEEE独立出版、EI稳定检索##高录用 快见刊 稳检索#】2024健康大数据与智能医疗国际会议(ICHIH 2024,12月13-15日)

#IEEE独立出版、EI稳定检索# #往届快至会后3-4个月检索# #高录用 快见刊 稳检索# 2024健康大数据与智能医疗国际会议&#xff08;ICHIH 2024&#xff09; 2024 International Conference on Health Big Data and Intelligent Healthcare 重要信息 大会官网&#xff1a;ww…

vue3中ElementPlus引入下载icon图标不显示透明问题解决教程方法

问题&#xff1a;今天用vue3开发&#xff0c;使用ElementPlus图标引入了但是不显示&#xff0c;是空白透明 解决&#xff1a; 1、在main.js中引入element-plus/icons-vue图标库 import * as ElIcons from element-plus/icons-vue; // 引入图标库 2、注册所有图标 // 注册所有…

1+X应急响应(网络)系统加固:

系统加固&#xff1a; 数据库的重要性&#xff1a; 数据库面临的风险&#xff1a; 数据库加固&#xff1a; 业务系统加固&#xff1a; 安全设备加固&#xff1a; 网络设备加固&#xff1a;

Web导出Excel表格

背景&#xff1a; 1. 后端主导实现 流程&#xff1a;前端调用到导出excel接口 -> 后端返回excel文件流 -> 浏览器会识别并自动下载 场景&#xff1a;大部分场景都有后端来做 2. 前端主导实现 流程&#xff1a;前端获取要导出的数据 -> 常规数据用插件处理成一个e…

【Linux】Github 仓库克隆速度慢/无法克隆的一种解决方法,利用 Gitee 克隆 Github 仓库

Github 经常由于 DNS 域名污染以及其他因素克隆不顺利。 一种办法是修改 hosts sudo gedit /etc/hosts加上一行 XXX.XXX.XXX.XXX github.comXXX 位置的 IP 可以通过网站查询 IP/服务器github.com的信息-站长工具 这种方法比较适合本身可以克隆&#xff0c;但是速度很慢的…

理解反射,学会反射:撬开私有性质(private)的属性与方法

看到这句话的时候证明&#xff1a;此刻你我都在努力 加油陌生人 个人主页&#xff1a;Gu Gu Study专栏&#xff1a;用Java学习数据结构系列喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹喜欢的话可以点个赞谢谢了。作者&#xff1a;小…

函数式编程(4) 纯函数

纯函数&#xff1a;每次调用时结果总是一样 这个函数不纯&#xff1a;返回的值有变化 这个函数不纯:因为使用了全局变量minAge 要让它变成纯函数需要 纯函数的好处 immutability/不变性 如果创建了一个对象 js中的const阻止了重新分配一个对象给book, 而并不能阻止给更改其titl…

【Golang】——Gin 框架中间件详解:从基础到实战

中间件是 Web 应用开发中常见的功能模块&#xff0c;Gin 框架支持自定义和使用内置的中间件&#xff0c;让你在请求到达路由处理函数前进行一系列预处理操作。这篇博客将涵盖中间件的概念、内置中间件的用法、如何编写自定义中间件&#xff0c;以及在实际应用中的一些最佳实践。…

Python爬虫知识体系-----requests-----持续更新

数据科学、数据分析、人工智能必备知识汇总-----Python爬虫-----持续更新&#xff1a;https://blog.csdn.net/grd_java/article/details/140574349 文章目录 一、安装和基本使用1. 安装2. 基本使用3. response常用属性 二、get请求三、post请求四、代理 一、安装和基本使用 1.…

【B+树特点】

B树的特点 B树是B树的一种变体&#xff0c;广泛用于数据库系统和文件系统中&#xff0c;特别是在索引结构中。B树在B树的基础上进行了优化&#xff0c;主要在数据存储和查询效率上有所提升。以下是B树的主要特点&#xff1a; 1. 所有数据存储在叶子节点 与B树不同&#xff0…

高翔【自动驾驶与机器人中的SLAM技术】学习笔记(十三)图优化SLAM的本质

一、直白解释slam与图优化的结合 我从b站上学习理解的这个概念。 视频的大概位置是1个小时以后&#xff0c;在第75min到80min之间。图优化SLAM是怎么一回事。 slam本身是有运动方程的&#xff0c;也就是运动状态递推方程&#xff0c;也就是预测过程。通过t1时刻&#xff0c…

PyCharm2024.2.4安装

一、官网下载 1.从下面的链接点进去 PyCharm: The Python IDE for data science and web development by JetBrains 2.进入官网后&#xff0c;下载pycharm安装包 3.点击下载能适配你系统的安装包 4.安装包下载完成 二、安装 1.下载完成后&#xff0c;打开点击右键&#xff…

WebSocket简易聊天室实现(有详细解释)

完整代码 Arata08/online-chat-demo 服务端: 1.编写配置类&#xff0c;扫描有 ServerEndpoint 注解的 Bean import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.s…

解决Xeyes: Error can‘t open display,远程X无法连通问题。

一、问题分析 提前申明&#xff1a; 本次实验使用REHL 8 进行操作&#xff01; 客户机 A 为X-Client &#xff0c;即远程X的客户端。 服务机 B 为X-Server&#xff0c;即远程X的服务端。 问题的所有操作均在已经配置好Xorg的前提下进行的&#xff0c;不知道不配置会有什么影响&…

19.UE5道具掉落

2-21 道具掉落&#xff0c;回血、回蓝、升级提升伤害_哔哩哔哩_bilibili 目录 1.道具的创建&#xff0c;道具功能的实现 2.随机掉落 1.道具的创建&#xff0c;道具功能的实现 新建Actor蓝图&#xff0c;并命名为道具总类&#xff0c;添加一个Niagara粒子组件和一个碰撞箱bo…

DevExpress WinForms中文教程:Data Grid - 如何绑定到实体框架数据源?

在本教程中&#xff0c;您将学习如何将DevExpress WinForms的网格控件绑定到实体框架数据源、如何使用数据注释属性来更改网格显示和管理数据的方式&#xff0c;以及如何将单元格值更改发送回数据源。 P.S&#xff1a;DevExpress WinForms拥有180组件和UI库&#xff0c;能为Wi…