ts学习2

JavaScript 中的每个值都有一组行为,您可以通过运行不同的操作来观察这些行为。这听起来很抽象,但作为一个简单的例子,考虑我们可能在名为 message 的变量上运行的一些操作。

// Accessing the property 'toLowerCase'
// on 'message' and then calling it
message.toLowerCase();// Calling 'message'
message();

如果我们将其分解,第一行可运行的代码会访问一个名为 toLowerCase 的属性,然后调用它。第二个尝试直接调用 message

但是假设我们不知道 message 的值——这很常见——我们不能可靠地说明尝试运行这些代码会得到什么结果。每个操作的行为完全取决于我们最初拥有的价值。

  • message 可以调用吗?
  • 它上面是否有一个名为 toLowerCase 的属性?
  • 如果是这样,toLowerCase 甚至可以调用吗?
  • 如果这两个值都是可调用的,它们会返回什么?

这些问题的答案通常是我们在编写 JavaScript 时牢记在心的事情,我们必须希望我们得到了正确的所有细节。

假设 message 是按以下方式定义的。

const message = "Hello World!";

正如您可能猜到的,如果我们尝试运行 message.toLowerCase(),我们将只得到相同的小写字符串。

那第二行代码呢?如果您熟悉 JavaScript,您会知道这会失败并出现异常:

TypeError: message is not a function

如果我们能避免这样的错误,那就太好了。

当我们运行我们的代码时,我们的 JavaScript 运行时选择做什么的方式是确定值的类型——它具有什么样的行为和能力。这就是 TypeError 所暗示的部分内容——它表示字符串 "Hello World!" 不能作为函数调用。

对于某些值,例如原语 string 和 number,我们可以在运行时使用 typeof 运算符识别它们的类型。但是对于其他的东西,比如函数,没有相应的运行时机制来识别它们的类型。例如,考虑这个函数:

function fn(x) {return x.flip();
}

我们可以通过阅读代码观察到,这个函数只有在给定一个具有可调用 flip 属性的对象时才能工作,但 JavaScript 不会以我们可以在代码运行时检查的方式显示这些信息。在纯 JavaScript 中,判断 fn 对特定值做了什么的唯一方法是调用它并查看会发生什么。这种行为使得在运行之前很难预测代码会做什么,这意味着在编写代码时更难知道代码会做什么。

这样看,类型就是描述哪些值可以传递给fn,哪些会崩溃的概念。JavaScript 仅真正提供动态类型 - 运行代码以查看发生了什么。

另一种方法是使用静态类型系统在运行之前预测预期的代码。

 静态类型检查

回想一下我们之前尝试将 string 作为函数调用而得到的 TypeError。大多数人不喜欢在运行他们的代码时遇到任何类型的错误——那些被认为是错误!当我们编写新代码时,我们会尽力避免引入新的错误。

如果我们只添加一点代码,保存我们的文件,重新运行代码,然后立即看到错误,我们也许可以快速隔离问题;但情况并非总是如此。我们可能没有对这个功能进行足够彻底的测试,所以我们可能永远不会真正遇到可能抛出的潜在错误!或者,如果我们有幸目睹了这个错误,我们可能最终会进行大规模的重构并添加许多我们不得不挖掘的不同代码。

理想情况下,我们可以有一个工具来帮助我们在代码运行之前找到这些错误。这就是像 TypeScript 这样的静态类型检查器所做的。静态类型系统描述了当我们运行程序时我们的值的形状和行为。像 TypeScript 这样的类型检查器使用这些信息并告诉我们什么时候事情可能会出轨。

const message = "hello!";message();

在我们首先运行代码之前,使用 TypeScript 运行最后一个示例会给我们一个错误消息。

 非异常故障

到目前为止,我们一直在讨论某些事情,比如运行时错误——JavaScript 运行时告诉我们它认为某些事情是荒谬的情况。出现这些情况是因为 ECMAScript 规范 明确说明了语言在遇到意外情况时应该如何表现。

例如,规范说尝试调用不可调用的东西应该会引发错误。也许这听起来像 "obvious behavior",但您可以想象访问对象上不存在的属性也会引发错误。相反,JavaScript 为我们提供了不同的行为并返回值 undefined

const user = {name: "Daniel",age: 26,
};user.location; // returns undefined

最终,静态类型系统必须调用其系统中应将哪些代码标记为错误,即使是不会立即抛出错误的 "valid" JavaScript。在 TypeScript 中,以下代码会产生关于 location 未定义的错误:

const user = {name: "Daniel",age: 26,
};user.location;

虽然有时这意味着在您可以表达的内容上进行权衡,但其目的是捕捉我们程序中的合法错误。TypeScript 捕获了很多合法的错误。

例如:错别字,

const announcement = "Hello World!";// How quickly can you spot the typos?
announcement.toLocaleLowercase();
announcement.toLocalLowerCase();// We probably meant to write this...
announcement.toLocaleLowerCase();

未调用的函数,

function flipCoin() {// Meant to be Math.random()return Math.random < 0.5;
}

或基本逻辑错误。

const value = Math.random() < 0.5 ? "a" : "b";
if (value !== "a") {// ...
} else if (value === "b") {// Oops, unreachable
}

 工具类型

当我们在代码中出错时,TypeScript 可以捕获错误。这很好,但 TypeScript 也可以从一开始就阻止我们犯这些错误。

类型检查器具有检查诸如我们是否正在访问变量和其他属性的正确属性之类的信息。一旦有了这些信息,它还可以开始建议您可能想要使用哪些属性。

这意味着 TypeScript 也可以用于编辑代码,核心类型检查器可以在您在编辑器中键入时提供错误消息和代码完成。这是人们在谈论 TypeScript 工具时经常提到的部分内容。

import express from "express";
const app = express();app.get("/", function (req, res) {res.sen
//       ^|
});app.listen(3000);

TypeScript 非常重视工具,这超出了您键入时的完成和错误。支持 TypeScript 的编辑器可以提供 "quick fixes" 以自动修复错误、重构以轻松重新组织代码,以及用于跳转到变量定义或查找对给定变量的所有引用的有用导航功能。所有这些都建立在类型检查器之上,并且是完全跨平台的,所以很可能是 你最喜欢的编辑器支持 TypeScript。

 tsc,TypeScript 编译器

我们一直在谈论类型检查,但我们还没有使用我们的类型检查器。让我们熟悉一下我们的新朋友 tsc,TypeScript 编译器。首先,我们需要通过 npm 获取它。

npm install -g typescript

这将全局安装 TypeScript 编译器 tsc。如果您希望从本地 node_modules 包运行 tsc,则可以使用 npx 或类似工具。

现在让我们移动到一个空文件夹并尝试编写我们的第一个 TypeScript 程序:hello.ts

// Greets the world.
console.log("Hello world!");

请注意,这里没有多余的装饰;这个 "hello world" 程序看起来和你用 JavaScript 编写的 "hello world" 程序一样。现在让我们通过运行 typescript 包为我们安装的命令 tsc 来检查它。

tsc hello.ts

Tada!

等等,到底 "tada" 什么?我们跑了 tsc,什么也没发生!好吧,没有类型错误,所以我们没有在控制台中得到任何输出,因为没有什么要报告的。

但再次检查 - 我们得到了一些文件输出。如果我们查看当前目录,我们会在 hello.ts 旁边看到一个 hello.js 文件。这是 tsc 编译或转换为纯 JavaScript 文件后我们的 hello.ts 文件的输出。如果我们检查内容,我们会看到 TypeScript 在处理 .ts 文件后会吐出什么:

// Greets the world.
console.log("Hello world!");

在这种情况下,TypeScript 几乎不需要转换,所以它看起来和我们写的一样。编译器试图发出看起来像人会写的东西的干净可读的代码。虽然这并不总是那么容易,但 TypeScript 会始终如一地缩进,注意我们的代码何时跨越不同的代码行,并试图保留注释。

如果我们确实引入了类型检查错误怎么办?让我们重写hello.ts

// This is an industrial-grade general-purpose greeter function:
function greet(person, date) {console.log(`Hello ${person}, today is ${date}!`);
}greet("Brendan");

如果我们再次运行 tsc hello.ts,请注意我们在命令行上收到错误!

Expected 2 arguments, but got 1.

TypeScript 告诉我们,我们忘记将参数传递给 greet 函数,这是理所当然的。到目前为止,我们只编写了标准的 JavaScript,但类型检查仍然能够发现我们代码的问题。感谢 TypeScript!

 使用错误触发

从上一个示例中您可能没有注意到的一件事是我们的 hello.js 文件再次更改。如果我们打开该文件,我们会看到内容与我们的输入文件看起来基本相同。考虑到 tsc 报告了关于我们的代码的错误,这可能有点令人惊讶,但这是基于 TypeScript 的核心价值之一:很多时候,你会比 TypeScript 更了解。

重申一下,类型检查代码限制了您可以运行的程序种类,因此需要权衡类型检查器认为可以接受的类型。大多数时候没关系,但在某些情况下,这些检查会妨碍您。例如,假设您将 JavaScript 代码迁移到 TypeScript 并引入类型检查错误。最终,您将开始为类型检查器清理东西,但原始的 JavaScript 代码已经可以工作了!为什么要将其转换为 TypeScript 会阻止您运行它?

所以 TypeScript 不会妨碍你。当然,随着时间的推移,您可能希望对错误更加防御,并使 TypeScript 的行为更加严格。在这种情况下,您可以使用 noEmitOnError 编译器选项。尝试更改您的 hello.ts 文件并使用该标志运行 tsc

tsc --noEmitOnError hello.ts

您会注意到 hello.js 永远不会更新。

 显式的类型

到目前为止,我们还没有告诉 TypeScript person 或 date 是什么。让我们编辑代码来告诉 TypeScript person 是一个 string,而 date 应该是一个 Date 对象。我们还将在 date 上使用 toDateString() 方法。

function greet(person: string, date: Date) {console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}

我们所做的是在 person 和 date 上添加类型注释来描述可以使用哪些类型的值来调用 greet。您可以将该签名读作 "greet takes a person of type string, and a date of type Date"。

有了这个,TypeScript 可以告诉我们 greet 可能被错误调用的其他情况。例如...

function greet(person: string, date: Date) {console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}greet("Maddison", Date());

嗯? TypeScript 在我们的第二个参数上报告了一个错误,但是为什么呢?

也许令人惊讶的是,在 JavaScript 中调用 Date() 返回一个 string。另一方面,用 new Date() 构造一个 Date 实际上给了我们所期望的结果。

无论如何,我们可以快速修复错误:

function greet(person: string, date: Date) {console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}greet("Maddison", new Date());

请记住,我们并不总是必须编写显式类型注释。在许多情况下,TypeScript 甚至可以为我们推断(或 "figure out")类型,即使我们省略它们。

let msg = "hello there!";

即使我们没有告诉 TypeScript msg 有 string 类型,它也能够弄清楚这一点。这是一个特性,当类型系统最终会推断出相同的类型时,最好不要添加注释。

注意:如果您将鼠标悬停在该单词上,则上一个代码示例中的消息气泡是您的编辑器将显示的内容。

 擦除的类型

让我们看看当我们用 tsc 编译上面的函数 greet 以输出 JavaScript 时会发生什么:

function greet(person: string, date: Date) {console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}greet("Maddison", new Date());

这里注意两点:

  1. 我们的 person 和 date 参数不再有类型注释。
  2. 我们的 "template string" - 那个使用反引号(` 字符)的字符串 - 被转换为带有连接的纯字符串。

稍后会详细介绍第二点,但现在让我们关注第一点。类型注释不是 JavaScript 的一部分(或者 ECMAScript 是迂腐的),所以实际上没有任何浏览器或其他运行时可以在未经修改的情况下运行 TypeScript。这就是 TypeScript 首先需要一个编译器的原因——它需要某种方式来剥离或转换任何 TypeScript 特定的代码,以便您可以运行它。大多数特定于 TypeScript 的代码都被删除了,同样地,我们的类型注释也被完全删除了。

记住:类型注释永远不会改变程序的运行时行为。

 降级

与上面的另一个区别是我们的模板字符串是从

`Hello ${person}, today is ${date.toDateString()}!`;

"Hello " + person + ", today is " + date.toDateString() + "!";

为什么会这样?

模板字符串是 ECMAScript 版本中的一项功能,称为 ECMAScript 2015(又名 ECMAScript 6、ES2015、ES6 等 - 不要问)。TypeScript 能够将代码从较新版本的 ECMAScript 重写为较旧的版本,例如 ECMAScript 3 或 ECMAScript 5(又名 ES3 和 ES5)。从 ECMAScript 的新版本或 "higher" 版本向下移动到旧版本或 "lower" 版本的过程有时称为降级。

默认情况下,TypeScript 以 ES3 为目标,这是一个非常旧的 ECMAScript 版本。通过使用 target 选项,我们可以选择更新一点的东西。使用 --target es2015 运行将 TypeScript 更改为以 ECMAScript 2015 为目标,这意味着代码应该能够在任何支持 ECMAScript 2015 的地方运行。所以运行 tsc --target es2015 hello.ts 会给我们以下输出:

function greet(person, date) {console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}
greet("Maddison", new Date());

虽然默认目标是 ES3,但当前绝大多数浏览器都支持 ES2015。因此,大多数开发人员可以安全地将 ES2015 或更高版本指定为目标,除非与某些古老的浏览器的兼容性很重要。

 严格性

不同的用户使用 TypeScript 在类型检查器中寻找不同的东西。有些人正在寻找一种更宽松的选择加入体验,它可以帮助验证他们程序的某些部分,并且仍然拥有不错的工具。这是 TypeScript 的默认体验,其中类型是可选的,推理采用最宽松的类型,并且不检查潜在的 null/undefined 值。就像 tsc 在面对错误时触发的一样,这些默认设置是为了不妨碍你。如果您要迁移现有的 JavaScript,那么这可能是理想的第一步。

相比之下,许多用户更喜欢让 TypeScript 尽可能多地立即验证,这就是该语言也提供严格设置的原因。这些严格性设置将静态类型检查从开关(无论是否检查您的代码)变成更接近调节器的东西。你把这个调节器调得越高,TypeScript 就会越多地为你检查。这可能需要一些额外的工作,但一般来说,从长远来看,它会为自己付出代价,并且可以进行更彻底的检查和更准确的工具。如果可能,新的代码库应始终打开这些严格性检查。

TypeScript 有几个可以打开或关闭的类型检查严格标志,除非另有说明,否则我们所有的示例都将在启用所有这些标志的情况下编写。CLI 中的 strict 标志或 tsconfig.json 中的 "strict": true 会同时将它们全部打开,但我们可以单独选择退出它们。您应该知道的两个最大的是 noImplicitAny 和 strictNullChecks。

 noImplicitAny

回想一下,在某些地方,TypeScript 不会尝试为我们推断类型,而是回退到最宽松的类型:any。这并不是可能发生的最糟糕的事情——毕竟,回退到 any 只是简单的 JavaScript 体验。

然而,使用 any 通常会破坏使用 TypeScript 的初衷。您的程序类型越多,您获得的验证和工具就越多,这意味着您在编写代码时遇到的错误就越少。打开 noImplicitAny 标志将对任何类型隐式推断为 any 的变量触发错误。

 strictNullChecks

默认情况下,像 null 和 undefined 这样的值可以分配给任何其他类型。这可以使编写一些代码更容易,但忘记处理 null 和 undefined 是世界上无数错误的原因 - 有些人认为它是 十亿美元的错误!strictNullChecks 标志使处理 null 和 undefined 更加明确,让我们不必担心是否忘记处理 null 和 undefined

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

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

相关文章

k8s环境使用Operator部署Seaweedfs集群(下)

作者&#xff1a;闫乾苓 文章目录4.4.3 部署seaweedfs集群4.4.4 验证集群运行状态4.4.5 测试集群功能4.4.3 部署seaweedfs集群 集群Yaml示例 apiVersion: seaweed.seaweedfs.com/v1 kind: Seaweed metadata:name: seaweed1namespace: default spec:image: chrislusf/seaweedf…

【橘子分布式】gRPC(理论篇)

一、简介 我们在前面学习了thrift rpc的知识&#xff0c;我们从其中接触到了IDL&#xff0c;编解码协议&#xff0c;服务的远程调用(调用远程服务就像在在本地调用一样)等各种概念。 其实我个人对thrift的使用并不多&#xff0c;我更多的是使用今天我们要提到的一个RPC框架称之…

OSPF高级特性之GR

一、概述OSPF GR(Graceful Restart),在路由器发生故障或管理员干预的情况下重启了OSPF进程时,重新构建控制平面时,转发平面不受影响,仍可以正常转发数据。在我们OSPF网络环境当中,假设路由器为框式路由器,通常框式路由器有多个主控板,当主主控板发生故障时会切换到备主控板上。…

iOS 构建配置与 AdHoc 打包说明

iOS 构建配置与 AdHoc 打包说明 1. 背景 在 iOS 项目中&#xff0c;通常需要支持 多个环境的构建和分发&#xff0c;比如&#xff1a; 开发环境 (Debug) → 本地调试内测环境 (AdHoc) → 提供 QA / 产品经理测试预发布环境 (AdHoc_Release) → 和正式版配置一致&#xff0c;但通…

【52】MFC入门到精通——MFC串口助手(二)---通信版(发送数据 、发送文件、数据转换、清空发送区、打开/关闭文件),附源码

文章目录1 完整 功能展示2 添加控件变量及声明2.1 添加控件及变量2.2 SerialPortDlg.h: 头文件3 函数实现3.1 数据发送3.1.2 写数据、字符串转3.2 发送文件3.2.1 打开文件3.2.2 发送文件3.3 清空发送区4 完整MFC项目项下载1 完整 功能展示 串口通信助手 页面展示&#xff0c;功…

笔试——Day12

文章目录第一题题目思路代码第二题题目&#xff1a;思路代码第三题题目&#xff1a;思路代码第一题 题目 删除公共字符 思路 模拟&#xff1a; 遇到需要删除的字符&#xff0c;则不添加到结果中 代码 第二题 题目&#xff1a; 两个链表的第一个公共结点 思路 模拟&#x…

SpringMVC @ResponseBody注解详解

概要ResponseBody是 Spring MVC 中的一个重要注解&#xff0c;用于指示方法的返回值应该直接作为 HTTP 响应体返回&#xff0c;而不是解析为视图名称。基本功能ResponseBody主要用于将Java对象转换为HTTP响应体&#xff08;通常是JSON或XML&#xff09;绕过视图解析器直接返回数…

剑指offer——模拟:顺时针打印矩阵

模拟vector.size返回的是矩阵的行数&#xff0c;vector[0].size返回的是矩阵的列数先排除传入的矩阵是空矩阵先计算上下左右的边界只要边界不重合&#xff0c;就不停止输出&#xff0c;完成一个部分的打印&#xff0c;就将当前的一个边界回收不可以在for循环结束的时候一起判断…

electron-vite实践成品项目

羊驼的工具箱 项目地址 推荐使用该版本 并且使用yarn进行安装 node版本:v22.16.0 技术栈&#xff1a;electron vue3 vite pinia vuetify3 sequelize sqlite Q:为什么vue3要用 vue2的写法 A:其实是因为刚开始用vue3的写法感觉超级恶心 对属性的赋值和方法的管理可观性…

自学中医笔记(一)

我的中医自学笔记 Q&A 自学原因&#xff1a;最开始我也不太信中医&#xff0c;我室友也说中医太玄学了。由于我从小一直都很瘦&#xff0c;吃饭每次都吃得少&#xff0c;上大学那会儿171cm最多也才101斤&#xff0c;而且一年胃病要犯好几次&#xff0c;后来无意中收获了一篇…

3.1 WPF画折线图、直方图、饼状图

本文看了博客WPF编程&#xff0c;Live Charts使用说明&#xff08;2&#xff09;——使用_func<chartpoint, string> labelpoint-CSDN博客&#xff0c;这里作为笔记用。 1.前端代码 前端XAML文件代码如下&#xff1a; <Window x:Class"livechart1.MainWindow&…

如何通过ATS/HTTPS数据防篡改来加密视频?

文章目录前言一、什么是ATS/HTTPS数据防篡改&#xff1f;二、ATS/HTTPS数据防篡改的实现原理三、如何零代码实现ATS/HTTPS数据防篡改来加密视频总结前言 未经保护的视频流极易在传输途中遭遇窃听、拦截或恶意篡改&#xff0c;不仅损害内容价值&#xff0c;更可能引发严重的安全…

Python并发模型:多线程与多进程的优劣对比与实战应用

文章目录多线程基础概念多进程基础概念多线程的优劣势多进程的优劣势实战应用&#xff1a;网络爬虫实战应用&#xff1a;图像处理Python作为一门功能强大的编程语言&#xff0c;提供了多种并发模型&#xff0c;使得我们能够在同一时间执行多个任务&#xff0c;从而提高程序的执…

Spring Boot 整合 Nacos 实战教程:服务注册发现与配置中心详解

Spring Boot 整合 Nacos 教程&#xff08;3000字&#xff09; 一、Nacos 简介 Nacos 是阿里巴巴开源的一个动态服务发现、配置管理和服务管理平台&#xff0c;致力于帮助开发者更轻松地构建云原生应用。它支持多种注册中心协议&#xff08;如 Dubbo、Spring Cloud、Kubernete…

VMware 虚拟机装 Linux Centos 7.9 保姆级教程(附资源包)

安装 VMware 17.5.1 centos 7.9 ​ 1、下载资源包&#xff08;虚拟机镜像&#xff09; VMware-17.5.1 安装包秘钥.zipLinux Centos 7.9 镜像 2、centos 7.9 下载地址 1、Centos 官网 2、阿里巴巴镜像站 3、查看网络命令 ifconfig 或 ip addr 4、登陆服务器 ssh stark192.168.3…

STM32超声波模块

一&#xff1a;超声波模块1&#xff1a;工作原理采用IO触发测距&#xff0c;给至少10us的高电平信号。 模块自动发送8个40KHz的方波&#xff0c;自动检测是否有信号返回。 有信号返回&#xff0c;通过IO输出一高电平&#xff0c;高电平持续时间就是超声波从发射到返回的时间声波…

RK3568项目(十一)--linux驱动开发之mipi屏幕调试

目录 一、引言 二、MIPI DSI 屏幕 ------>2.1、MIPI联盟 ------------>2.1.1、多媒体部分 ------------>2.1.2、硬件协议 ------------>2.1.3、D-PHY功能模式及速率 ------------>2.1.4、分辨率计算 ------>2.2、MIPI-DSI硬件连接 ------>2.3、传…

C语言小游戏——飞机大战

目录 引言 开发环境与工具准备 1. 开发环境配置 2. 资源文件准备 游戏设计与架构 1. 游戏核心数据结构 2. 游戏全局变量 游戏核心功能实现 1. 游戏初始化 2. 游戏主循环 3. 游戏渲染 4. 游戏状态更新 关键游戏机制实现 1. 敌机生成系统 2. 碰撞检测系统 3. 敌机…

SQLite的可视化界面软件的安装

1、如下图所示&#xff0c;DB Browser软件&#xff0c;在压缩包中。2、首先解压到一个文件夹中。例如&#xff08;D:\\DB Browser&#xff09;文件夹。解压后的内容如下图。3、将解压后的DB Browser文件夹&#xff0c;剪切到D:\Program Files\目录中。如下两图。win10操作系统下…

基于 STM32H743VIT6 的边缘 AI 实践:猫咪叫声分类 CNN 网络部署实战(已验证)中一些bug总结

前言前面发了一篇文章基于 STM32H743VIT6 的边缘 AI 实践&#xff1a;猫咪叫声分类 CNN 网络部署实战&#xff08;已验证&#xff09;。这里面有一些我遇到过的bug&#xff0c;当时基本都花了很长的时间才解决。这里将这些bug总结一下方便后续查阅。1.使用cubemx插件解析AI模型…