前言
截止到小编写这篇的时候,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
能正常看到版本号就说明安装成功了。
接下来,我们开始来编译我们第一个 .ts
文件。
创建 test.ts
文件:
const articleName: string = '橙某人';
console.log(articleName);
直接编译命令:
tsc test.ts
执行后,将会生成一个 .js
文件,并且 TS
代码也会被编译成普通的 ES5
代码了。
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
直接执行 .ts
文件:
ts-node test.ts
😲 这种方式是不是就稍微好玩了一些了呢❓
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();
不知道你有没有注意到,上面定义类型的时候,类型名称首字母都是小写字母,这是因为首字母大写的 String
、Number
、 Boolean
属于 JS
的内置对象。
(下面会解释两者的区别)
内置对象
JS
的内置对象有很多,如 Number
、String
、Date
、Error
、RegExp
等等。
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
谁,类型就是谁。
注意🔉:
没有大写的
Null
或Undefined
。
undefined
和null
既可以作为值,也可以作为类型,取决于在哪里使用它们。
undefined
与null
是所有类型的子类型,在非严格模式下,可以赋值给任何类型。
🍊关于 number/string/boolean
与 Number/String/Boolean
的区别?
let str: string = '橙某人';
let Str: String = new String('橙某人');
Str = str; // ✅
str = Str; // ❌
可以看到大写是包含小写的,你也可以认为小写是指更细致的类型,大写是指较宽松的类型。
其本质是因为 Number
是 number
的一个包装类型,关于什么是包装类型,可以看看这篇文章的介绍,传送门。
下面贴上一张图,从上到下,类型越来越严格,下面的类型能分配给上面的类型,反之不行。
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
通关秘籍是打算成写一篇文章,与小编另外两篇通关秘籍是一个系列,奈何小编吭哧吭哧在编辑器上写了两三周,复制过来却发不了。。。😭
至此,本篇文章就写完啦,撒花撒花。
希望本文对你有所帮助,如有任何疑问,期待你的留言哦。
老样子,点赞+评论=你会了,收藏=你精通了。
原文链接:https://juejin.cn/post/7312722655224741900 作者:橙某人