🚀🚀🚀Typescript通关秘籍(一)🔥🔥🔥

前言

截止到小编写这篇的时候,Typescript 已经发布到 5.3.2 版本了,好像现在写这文章是有点”迟”了?😰

不过,无所谓,就当一个总结,也方便以后随时能查阅叭。

接下来,咱们开始愉快的学习之旅,冲冲冲。👻

简介

开头一问:”What is TypeScript?”

一句话总结:”TypeScript 是 JavaScript 的一个超集。”

直接放上官网地址:传送门

那个谁(行业中的名人)曾说:”Javascript 早期拼命把 Type 从 Javscript 中移除,现在却又努力要把它加回来。” 😗😗😗

这里,咱们就不具体追本溯源了,这不重要,我们只要关心其中利弊如何即可。

优点

  • 增加代码的可读性和可维护性,比如接口请求参数与接口响应数据,我们能直接通过代码就能知道需要的数据类型。

  • 在编译阶段就能发现大部分错误,更好的避免了线上bug。

  • 增强了编译器的补全、接口提示功能。

缺点

  • 学习成本:有一定的学习成本,接口、泛型、枚举、类等新型概念需要去学习。

  • 开发成本:开发前期会增加一些开发成本,但后期维护就会相对比较简单。

  • 时间成本:TS的编译需要时间,开发启动和打包时间成本会增加。

  • 风险成本:一些JS库需要做兼容,需要手动提供声明文件。

环境配置

由于 TS 代码无法像 JS 一样直接在浏览器中运行,也不能在 Node 环境中运行,所以,要执行 TS 需要一个转译的过程,将其转成 JS 才能被执行。

因此,在正式学习 TS 之前,你还需要先配置 TS 的环境。

以下,小编提供了三种方式让你能执行 TS 代码,就看你钟爱哪种了。😉

tsc

全局安装 TS

npm install -g typescript

(作为一名前端程序猿,你还没安装❓❓❓相信大部分前端小伙伴应该都是安装了的)

检查一下安装是否成功:

tsc -v

🚀🚀🚀Typescript通关秘籍(一)🔥🔥🔥

能正常看到版本号就说明安装成功了。

接下来,我们开始来编译我们第一个 .ts 文件。

创建 test.ts 文件:

const articleName: string = '橙某人';
console.log(articleName);

直接编译命令:

tsc test.ts

执行后,将会生成一个 .js 文件,并且 TS 代码也会被编译成普通的 ES5 代码了。

🚀🚀🚀Typescript通关秘籍(一)🔥🔥🔥

tsc 命令后面可以接受一些参数,如:

// 编译 src 目录的所有 .ts 文件
tsc src/*.ts

// 指定编译配置文件
tsc --project tsconfig.production.json

// 只生成类型声明文件,不编译出 JS 文件
tsc index.js --declaration --emitDeclarationOnly

// 多个 TS 文件编译成单个 JS 文件
tsc app.ts util.ts --target esnext --outfile index.js

更多参数信息可以查阅官网:传送门

阮一峰大神的中文版解释:传送门

在使用 tsc 命令时,后面如果不带任何参数,则会获取读取 tsconfig.json 文件的配置信息。如果没有提供该文件,则会抛出错误,无法编译。

tsc 的命令行参数,大部分与 tsconfig.json 文件的属性一一对应。

ts-node

tsc 虽然能帮我们将 TS 转成 JS,但有时开发测试,这种方式还是很不方便。😐

ts-node:能帮我们在 Node 环境中直接执行 .ts 文件。

全局安装 ts-node

npm install -g ts-node

检查安装是否成功:

ts-node -v

🚀🚀🚀Typescript通关秘籍(一)🔥🔥🔥

直接执行 .ts 文件:

ts-node test.ts

🚀🚀🚀Typescript通关秘籍(一)🔥🔥🔥

😲 这种方式是不是就稍微好玩了一些了呢❓

playground

最后,TS 官方也给我们提供了一个线上的 TS 环境,方便我们随时随地能进行 TS 代码的测试。

传送门 👈👈👈

tsconfig.json 文件

tsconfig.json 文件是 TS 的配置文件,一般放置于项目的根目录下。

它主要提供给 tsc 编译器使用,tsc 会在当前目录下搜索 tsconfig.json 文件,如果不存在,就会到上一级目录中搜索,直到找到为止,最后找不到会抛出错误。

你可以手动创建 tsconfig.json 文件,也可以通过 tsc 来自动创建。

tsc --init

以下列举部分配置的说明,一般应该也足够用了的,更多配置的可以到官网上查阅。

{
"compilerOptions": {
"incremental": true, // TS编译器在第一次编译之后会生成一个存储编译信息的文件,第二次编译会在第一次的基础上进行增量编译,可以提高编译的速度
"tsBuildInfoFile": "./buildFile", // 增量编译文件的存储位置
"diagnostics": true, // 打印诊断信息
"target": "ES5", // 目标语言的版本
"module": "CommonJS", // 生成代码的模板标准
"outFile": "./app.js", // 将多个相互依赖的文件生成一个文件,可以用在AMD模块中,即开启时应设置"module": "AMD",
"lib": ["DOM", "ES2015", "ScriptHost", "ES2019.Array"], // TS需要引用的库,即声明文件,es5 默认引用dom、es5、scripthost,如需要使用es的高级版本特性,通常都需要配置,如es8的数组新特性需要引入"ES2019.Array",
"allowJS": true, // 允许编译器编译JS,JSX文件
"checkJs": true, // 允许在JS文件中报错,通常与allowJS一起使用
"outDir": "./dist", // 指定输出目录
"rootDir": "./", // 指定输出文件目录(用于输出),用于控制输出目录结构
"declaration": true, // 生成声明文件,开启后会自动生成声明文件
"declarationDir": "./file", // 指定生成声明文件存放目录
"emitDeclarationOnly": true, // 只生成声明文件,而不会生成js文件
"sourceMap": true, // 生成目标文件的sourceMap文件
"inlineSourceMap": true, // 生成目标文件的inline SourceMap,inline SourceMap会包含在生成的js文件中
"declarationMap": true, // 为声明文件生成sourceMap
"typeRoots": [], // 声明文件目录,默认时node_modules/@types
"types": [], // 加载的声明文件包
"removeComments":true, // 删除注释
"noEmit": true, // 不输出文件,即编译后不会生成任何js文件
"noEmitOnError": true, // 发送错误时不输出任何文件
"noEmitHelpers": true, // 不生成helper函数,减小体积,需要额外安装,常配合importHelpers一起使用
"importHelpers": true, // 通过tslib引入helper函数,文件必须是模块
"downlevelIteration": true, // 降级遍历器实现,如果目标源是es3/5,那么遍历器会有降级的实现
"strict": true, // 开启所有严格的类型检查
"alwaysStrict": true, // 在代码中注入'use strict'
"noImplicitAny": true, // 不允许隐式的any类型
"strictNullChecks": true, // 不允许把null、undefined赋值给其他类型的变量
"strictFunctionTypes": true, // 不允许函数参数双向协变
"strictPropertyInitialization": true, // 类的实例属性必须初始化
"strictBindCallApply": true, // 严格的bind/call/apply检查
"noImplicitThis": true, // 不允许this有隐式的any类型
"noUnusedLocals": true, // 检查只声明、未使用的局部变量(只提示不报错)
"noUnusedParameters": true, // 检查未使用的函数参数(只提示不报错)
"noFallthroughCasesInSwitch": true, // 防止switch语句贯穿(即如果没有break语句后面不会执行)
"noImplicitReturns": true, //每个分支都会有返回值
"esModuleInterop": true, // 允许export=导出,由import from 导入
"allowUmdGlobalAccess": true, // 允许在模块中全局变量的方式访问umd模块
"moduleResolution": "node", // 模块解析策略,ts默认用node的解析策略,即相对的方式导入
"baseUrl": "./", // 解析非相对模块的基地址,默认是当前目录
"paths": { // 路径映射,相对于baseUrl
// 如使用jq时不想使用默认版本,而需要手动指定版本,可进行如下配置
"jquery": ["node_modules/jquery/dist/jquery.min.js"]
},
"rootDirs": ["src","out"], // 将多个目录放在一个虚拟目录下,用于运行时,即编译后引入文件的位置可能发生变化,这也设置可以虚拟src和out在同一个目录下,不用再去改变路径也不会报错
"listEmittedFiles": true, // 打印输出文件
"listFiles": true// 打印编译的文件(包括引用的声明文件)
}
// 指定一个匹配列表(属于自动指定该路径下的所有ts相关文件)
"include": [
"src/**/*"
],
// 指定一个排除列表(include的反向操作)
"exclude": [
"demo.ts"
],
// 指定哪些文件使用该配置(需要手动一个个指定文件)
"files": [
"demo.ts"
]
}

基础类型注解

八种基础类型

到目前为止,JS 中一共有八种数据类型:number、string、boolean、null、undefined、object、symbol(ES6)、bigint(ES10)

let a1: string = '橙某人';
let a2: number = 1;
let a3: boolean = true;
let a4: null = null;
let a5: undefined = undefined;
let a6: object = {};
let a7: bigint = 1n;
let a8: symbol = Symbol();

不知道你有没有注意到,上面定义类型的时候,类型名称首字母都是小写字母,这是因为首字母大写的 StringNumberBoolean 属于 JS 的内置对象。
(下面会解释两者的区别)

内置对象

JS 的内置对象有很多,如 NumberStringDateErrorRegExp 等等。

let aa1: String = new String('橙某人');
let aa2: Number = new Number(1);
let aa3: Boolean = new Boolean(true); 
// let aa4: Null = null; ❌
// let aa5: Undefined = undefined; ❌
let aa6: Object = new Object({});
let aa7: BigInt = BigInt(1n);
let aa8: Symbol = Symbol();
let date: Date = new Date();
let error: Error = new Error('这是一个错误');
let reg: RegExp = new RegExp(/\a/);

大部分 ECMAScript 内置对象的类型定义: new 谁,类型就是谁。

注意🔉:

没有大写的 NullUndefined

undefinednull 既可以作为值,也可以作为类型,取决于在哪里使用它们。

undefinednull 是所有类型的子类型,在非严格模式下,可以赋值给任何类型。

🍊关于 number/string/booleanNumber/String/Boolean 的区别?

let str: string = '橙某人';
let Str: String = new String('橙某人');
Str = str; // ✅
str = Str; // ❌

可以看到大写是包含小写的,你也可以认为小写是指更细致的类型,大写是指较宽松的类型。

其本质是因为 Numbernumber 的一个包装类型,关于什么是包装类型,可以看看这篇文章的介绍,传送门

下面贴上一张图,从上到下,类型越来越严格,下面的类型能分配给上面的类型,反之不行

🚀🚀🚀Typescript通关秘籍(一)🔥🔥🔥

DOM

DOM (Document Object Model) 即文档对象模型,指 Web 上构成文档结构和内容的对象的数据表示。说直白点就是指那些 HTML 标签在 JS 中的数据表示。

而在 TS 中有三种方式能定义 DOM 类型。

  • 其一,一般大部分的标签类型定义形式都是 HTML(标签名)Element
let dom1: HTMLDivElement = document.createElement('div');
let dom2: HTMLInputElement = document.createElement('input');
let dom3: HTMLLabelElement = document.createElement('label');
  • 其二,如果是特殊的标签类型,可以定义成 HTMLElement 类型。
let dom1: HTMLElement = document.createElement('header');
let dom2: HTMLElement = document.createElement('footer');
let dom3: HTMLElement = document.createElement('section');
  • 最后,Element 类型专治花里胡哨。
let dom1: Element = document.createElement('div');
let dom2: Element = document.createElement('input');
let dom3: Element = document.createElement('label');

当然,如果你是一个比较严谨的人,那么你可以去 TS 源码中查看每个 DOM 的类型定义。传送门

以下小编拷贝了一些过来,可以作为一个参考👻:

interface HTMLElementTagNameMap {
"a": HTMLAnchorElement;
"abbr": HTMLElement;
"address": HTMLElement;
"area": HTMLAreaElement;
"article": HTMLElement;
"aside": HTMLElement;
"audio": HTMLAudioElement;
"b": HTMLElement;
"base": HTMLBaseElement;
"bdi": HTMLElement;
"bdo": HTMLElement;
"blockquote": HTMLQuoteElement;
"body": HTMLBodyElement;
"br": HTMLBRElement;
"button": HTMLButtonElement;
"canvas": HTMLCanvasElement;
"caption": HTMLTableCaptionElement;
"cite": HTMLElement;
"code": HTMLElement;
"col": HTMLTableColElement;
"colgroup": HTMLTableColElement;
"data": HTMLDataElement;
"datalist": HTMLDataListElement;
"dd": HTMLElement;
"del": HTMLModElement;
"details": HTMLDetailsElement;
"dfn": HTMLElement;
"dialog": HTMLDialogElement;
"dir": HTMLDirectoryElement;
"div": HTMLDivElement;
"dl": HTMLDListElement;
"dt": HTMLElement;
"em": HTMLElement;
"embed": HTMLEmbedElement;
"fieldset": HTMLFieldSetElement;
"figcaption": HTMLElement;
"figure": HTMLElement;
"font": HTMLFontElement;
"footer": HTMLElement;
"form": HTMLFormElement;
"frame": HTMLFrameElement;
"frameset": HTMLFrameSetElement;
"h1": HTMLHeadingElement;
"h2": HTMLHeadingElement;
"h3": HTMLHeadingElement;
"h4": HTMLHeadingElement;
"h5": HTMLHeadingElement;
"h6": HTMLHeadingElement;
"head": HTMLHeadElement;
"header": HTMLElement;
"hgroup": HTMLElement;
"hr": HTMLHRElement;
"html": HTMLHtmlElement;
"i": HTMLElement;
"iframe": HTMLIFrameElement;
"img": HTMLImageElement;
"input": HTMLInputElement;
"ins": HTMLModElement;
"kbd": HTMLElement;
"label": HTMLLabelElement;
"legend": HTMLLegendElement;
"li": HTMLLIElement;
"link": HTMLLinkElement;
"main": HTMLElement;
"map": HTMLMapElement;
"mark": HTMLElement;
"marquee": HTMLMarqueeElement;
"menu": HTMLMenuElement;
"meta": HTMLMetaElement;
"meter": HTMLMeterElement;
"nav": HTMLElement;
"noscript": HTMLElement;
"object": HTMLObjectElement;
"ol": HTMLOListElement;
"optgroup": HTMLOptGroupElement;
"option": HTMLOptionElement;
"output": HTMLOutputElement;
"p": HTMLParagraphElement;
"param": HTMLParamElement;
"picture": HTMLPictureElement;
"pre": HTMLPreElement;
"progress": HTMLProgressElement;
"q": HTMLQuoteElement;
"rp": HTMLElement;
"rt": HTMLElement;
"ruby": HTMLElement;
"s": HTMLElement;
"samp": HTMLElement;
"script": HTMLScriptElement;
"section": HTMLElement;
"select": HTMLSelectElement;
"slot": HTMLSlotElement;
"small": HTMLElement;
"source": HTMLSourceElement;
"span": HTMLSpanElement;
"strong": HTMLElement;
"style": HTMLStyleElement;
"sub": HTMLElement;
"summary": HTMLElement;
"sup": HTMLElement;
"table": HTMLTableElement;
"tbody": HTMLTableSectionElement;
"td": HTMLTableDataCellElement;
"template": HTMLTemplateElement;
"textarea": HTMLTextAreaElement;
"tfoot": HTMLTableSectionElement;
"th": HTMLTableHeaderCellElement;
"thead": HTMLTableSectionElement;
"time": HTMLTimeElement;
"title": HTMLTitleElement;
"tr": HTMLTableRowElement;
"track": HTMLTrackElement;
"u": HTMLElement;
"ul": HTMLUListElement;
"var": HTMLElement;
"video": HTMLVideoElement;
"wbr": HTMLElement;
}

🍊关于如何定义批量获取的 DOM 类型?

let domArray1: NodeList = document.querySelectorAll('div');
// 以泛型的形式,后面会讲泛型
let domArray2: NodeListOf<HTMLDivElement | HTMLElement> = document.querySelectorAll('div') || document.querySelectorAll('p')

BOM

BOM (Browser Object Model) 即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window

TS 对于 BOM 对象的定义比较简单,只要首字母大写即可完成类型的定义。

let win: Window = window;
let doc: Document = document;
let his: History = history;
let loc: Location = location;
let nav: Navigator = navigator;
let scr: Screen = screen;

不过也有一些是比较特殊的,这些都可以从 TS 的源码文件中查询得到。

let coo: string = document.cookie
let locS: Storage = localStorage;

类型注解与类型推断

类型注解:指我们明确的注解一个变量的类型。

let str: string = '橙某人';
let num: number = 1;
let bool: boolean = true;

类型推断:指 TS 会根据上下文环境自动帮我们推断出变量的类型,无须我们再写明类型注解。

let articleName = '橙某人';
let num = 1;
let bool = true;

以上两段代码是等价的。


本来这个 TS 通关秘籍是打算成写一篇文章,与小编另外两篇通关秘籍是一个系列,奈何小编吭哧吭哧在编辑器上写了两三周,复制过来却发不了。。。😭

🚀🚀🚀Typescript通关秘籍(一)🔥🔥🔥

🚀🚀🚀Typescript通关秘籍(一)🔥🔥🔥


至此,本篇文章就写完啦,撒花撒花。

🚀🚀🚀Typescript通关秘籍(一)🔥🔥🔥

希望本文对你有所帮助,如有任何疑问,期待你的留言哦。
老样子,点赞+评论=你会了,收藏=你精通了。

原文链接:https://juejin.cn/post/7312722655224741900 作者:橙某人

(0)
上一篇 2023年12月16日 下午5:08
下一篇 2023年12月17日 上午10:00

相关推荐

发表回复

登录后才能评论