🚀🚀🚀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

javascript 复制代码
npm install -g typescript

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

检查一下安装是否成功:

javascript 复制代码
tsc -v

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

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

创建 test.ts 文件:

javascript 复制代码
const articleName: string = '橙某人';
console.log(articleName);

直接编译命令:

javascript 复制代码
tsc test.ts

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

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

lua 复制代码
// 编译 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

javascript 复制代码
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 来自动创建。

javascript 复制代码
tsc --init

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

json 复制代码
{
  "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)

javascript 复制代码
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 等等。

javascript 复制代码
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 的区别?

javascript 复制代码
let str: string = '橙某人';
let Str: String = new String('橙某人');

Str = str; // ✅
str = Str; // ❌

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

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

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

DOM

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

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

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

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

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

javascript 复制代码
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 类型?

javascript 复制代码
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 对象的定义比较简单,只要首字母大写即可完成类型的定义。

javascript 复制代码
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 的源码文件中查询得到。

javascript 复制代码
let coo: string = document.cookie
let locS: Storage = localStorage;

类型注解与类型推断

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

javascript 复制代码
let str: string = '橙某人';
let num: number = 1;
let bool: boolean = true;

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

javascript 复制代码
let articleName = '橙某人';
let num = 1;
let bool = true;

以上两段代码是等价的。


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


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

希望本文对你有所帮助,如有任何疑问,期待你的留言哦。

老样子,点赞+评论=你会了,收藏=你精通了。

相关推荐
OpenTiny社区9 分钟前
把 SearchBox 塞进项目,搜索转化率怒涨 400%?
前端·vue.js·github
编程猪猪侠39 分钟前
Tailwind CSS 自定义工具类与主题配置指南
前端·css
qhd吴飞43 分钟前
mybatis 差异更新法
java·前端·mybatis
YGY Webgis糕手之路1 小时前
OpenLayers 快速入门(九)Extent 介绍
前端·经验分享·笔记·vue·web
患得患失9491 小时前
【前端】【vueDevTools】使用 vueDevTools 插件并修改默认打开编辑器
前端·编辑器
ReturnTrue8681 小时前
Vue路由状态持久化方案,优雅实现记住表单历史搜索记录!
前端·vue.js
UncleKyrie1 小时前
一个浏览器插件帮你查看Figma设计稿代码图片和转码
前端
遂心_1 小时前
深入解析前后端分离中的 /api 设计:从路由到代理的完整指南
前端·javascript·api
你听得到111 小时前
Flutter - 手搓一个日历组件,集成单日选择、日期范围选择、国际化、农历和节气显示
前端·flutter·架构
风清云淡_A2 小时前
【REACT18.x】CRA+TS+ANTD5.X封装自定义的hooks复用业务功能
前端·react.js