TypeScript 基础教程,适合新手

2023-11-13

TypeScript 基本用法

本章介绍 TypeScript 的一些最基本的语法和用法。

最全教程:https://tut.qzxdp.cn/typescript/
在线工具:https://tools.qzxdp.cn/

类型声明

TypeScript 代码最明显的特征,就是为 JavaScript 变量加上了类型声明。

let foo:string;

上面示例中,变量foo的后面使用冒号,声明了它的类型为string

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

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

上面示例中,函数toString()的参数num的类型是number。参数列表的圆括号后面,声明了返回值的类型是string。更详细的介绍,参见《函数》一章。

注意,变量的值应该与声明的类型一致,如果不一致,TypeScript 就会报错。

// 报错
let foo:string = 123;

上面示例中,变量foo的类型是字符串,但是赋值为数值123,TypeScript 就报错了。

另外,TypeScript 规定,变量只有赋值后才能使用,否则就会报错。

let x:number;
console.log(x) // 报错

上面示例中,变量x没有赋值就被读取,导致报错。而 JavaScript 允许这种行为,不会报错,没有赋值的变量会返回undefined

类型推断

类型声明并不是必需的,如果没有,TypeScript 会自己推断类型。

let foo = 123;

上面示例中,变量foo并没有类型声明,TypeScript 就会推断它的类型。由于它被赋值为一个数值,因此 TypeScript 推断它的类型为number

后面,如果变量foo更改为其他类型的值,跟推断的类型不一致,TypeScript 就会报错。

let foo = 123;
foo = 'hello'; // 报错

上面示例中,变量foo的类型推断为number,后面赋值为字符串,TypeScript 就报错了。

TypeScript 也可以推断函数的返回值。

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

上面示例中,函数toString()没有声明返回值的类型,但是 TypeScript 推断返回的是字符串。正是因为 TypeScript 的类型推断,所以函数返回值的类型通常是省略不写的。

从这里可以看到,TypeScript 的设计思想是,类型声明是可选的,你可以加,也可以不加。即使不加类型声明,依然是有效的 TypeScript 代码,只是这时不能保证 TypeScript 会正确推断出类型。由于这个原因。所有 JavaScript 代码都是合法的 TypeScript 代码。

这样设计还有一个好处,将以前的 JavaScript 项目改为 TypeScript 项目时,你可以逐步地为老代码添加类型,即使有些代码没有添加,也不会无法运行。

TypeScript 的编译

JavaScript 的运行环境(浏览器和 Node.js)不认识 TypeScript 代码。所以,TypeScript 项目要想运行,必须先转为 JavaScript 代码,这个代码转换的过程就叫做“编译”(compile)。

TypeScript 官方没有做运行环境,只提供编译器。编译时,会将类型声明和类型相关的代码全部删除,只留下能运行的 JavaScript 代码,并且不会改变 JavaScript 的运行结果。

因此,TypeScript 的类型检查只是编译时的类型检查,而不是运行时的类型检查。一旦代码编译为 JavaScript,运行时就不再检查类型了。

值与类型

学习 TypeScript 需要分清楚“值”(value)和“类型”(type)。

“类型”是针对“值”的,可以视为是后者的一个元属性。每一个值在 TypeScript 里面都是有类型的。比如,3是一个值,它的类型是number

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

这一点务必牢记。TypeScript 项目里面,其实存在两种代码,一种是底层的“值代码”,另一种是上层的“类型代码”。前者使用 JavaScript 语法,后者使用 TypeScript 的类型语法。

它们是可以分离的,TypeScript 的编译过程,实际上就是把“类型代码”全部拿掉,只保留“值代码”。

编写 TypeScript 项目时,不要混淆哪些是值代码,哪些是类型代码。

TypeScript Playground

最简单的 TypeScript 使用方法,就是使用官网的在线编译页面,叫做 TypeScript Playground

只要打开这个网页,把 TypeScript 代码贴进文本框,它就会在当前页面自动编译出 JavaScript 代码,还可以在浏览器执行编译产物。如果编译报错,它也会给出详细的报错信息。

这个页面还具有支持完整的 IDE 支持,可以自动语法提示。此外,它支持把代码片段和编译器设置保存成 URL,分享给他人。

本书的示例都建议放到这个页面,进行查看和编译。

tsc 编译器

TypeScript 官方提供的编译器叫做 tsc,可以将 TypeScript 脚本编译成 JavaScript 脚本。本机想要编译 TypeScript 代码,必须安装 tsc。

根据约定,TypeScript 脚本文件使用.ts后缀名,JavaScript 脚本文件使用.js后缀名。tsc 的作用就是把.ts脚本转变成.js脚本。

安装

tsc 是一个 npm 模块,使用下面的命令安装(必须先安装 npm)。

$ npm install -g typescript

上面命令是全局安装 tsc,也可以在项目中将 tsc 安装为一个依赖模块。

安装完成后,检查一下是否安装成功。

# 或者 tsc --version
$ tsc -v
Version 5.1.6

上面命令中,-v--version参数可以输出当前安装的 tsc 版本。

帮助信息

-h--help参数输出帮助信息。

$ tsc -h

默认情况下,“–help”参数仅显示基本的可用选项。我们可以使用“–all”参数,查看完整的帮助信息。

$ tsc --all

编译脚本

安装 tsc 之后,就可以编译 TypeScript 脚本了。

tsc命令后面,加上 TypeScript 脚本文件,就可以将其编译成 JavaScript 脚本。

$ tsc app.ts

上面命令会在当前目录下,生成一个app.js脚本文件,这个脚本就完全是编译后生成的 JavaScript 代码。

tsc命令也可以一次编译多个 TypeScript 脚本。

$ tsc file1.ts file2.ts file3.ts

上面命令会在当前目录生成三个 JavaScript 脚本文件file1.jsfile2.jsfile3.js

tsc 有很多参数,可以调整编译行为。

(1)–outFile

如果想将多个 TypeScript 脚本编译成一个 JavaScript 文件,使用--outFile参数。

$ tsc file1.ts file2.ts --outFile app.js

上面命令将file1.tsfile2.ts两个脚本编译成一个 JavaScript 文件app.js

(2)–outDir

编译结果默认都保存在当前目录,--outDir参数可以指定保存到其他目录。

$ tsc app.ts --outDir dist

上面命令会在dist子目录下生成app.js

(3)–target

为了保证编译结果能在各种 JavaScript 引擎运行,tsc 默认会将 TypeScript 代码编译成很低版本的 JavaScript,即3.0版本(以es3表示)。这通常不是我们想要的结果。

这时可以使用--target参数,指定编译后的 JavaScript 版本。建议使用es2015,或者更新版本。

$ tsc --target es2015 app.ts

编译错误的处理

编译过程中,如果没有报错,tsc命令不会有任何显示。所以,如果你没有看到任何提示,就表示编译成功了。

如果编译报错,tsc命令就会显示报错信息,但是这种情况下,依然会编译生成 JavaScript 脚本。

举例来说,下面是一个错误的 TypeScript 脚本app.ts

// app.ts
let foo:number = 123;
foo = 'abc'; // 报错

上面示例中,变量foo是数值类型,赋值为字符串,tsc命令编译这个脚本就会报错。

$ tsc app.ts

app.ts:2:1 - error TS2322: Type 'string' is not assignable to type 'number'.

2 foo = 'abc';
  ~~~

Found 1 error in app.ts:2

上面示例中,tsc命令输出报错信息,表示变量foo被错误地赋值为字符串。

这种情况下,编译产物app.js还是会照样生成,下面就是编译后的结果。

// app.js
var foo = 123;
foo = 'abc';

可以看到,尽管有错,tsc 依然原样将 TypeScript 编译成 JavaScript 脚本。

这是因为 TypeScript 团队认为,编译器的作用只是给出编译错误,至于怎么处理这些错误,那就是开发者自己的判断了。开发者更了解自己的代码,所以不管怎样,编译产物都会生成,让开发者决定下一步怎么处理。

如果希望一旦报错就停止编译,不生成编译产物,可以使用--noEmitOnError参数。

$ tsc --noEmitOnError app.ts

上面命令在报错后,就不会生成app.js

tsc 还有一个--noEmit参数,只检查类型是否正确,不生成 JavaScript 文件。

$ tsc --noEmit app.ts

上面命令只检查是否有编译错误,不会生成app.js

tsc 命令的更多参数,详见《tsc 编译器》一章。

tsconfig.json

TypeScript 允许将tsc的编译参数,写在配置文件tsconfig.json。只要当前目录有这个文件,tsc就会自动读取,所以运行时可以不写参数。

$ tsc file1.js file2.js --outFile dist/app.js

上面这个命令写成tsconfig.json,就是下面这样。

{
  "files": ["file1.ts", "file2.ts"],
  "compilerOptions": {
    "outFile": "dist/app.js"
  }
}

有了这个配置文件,编译时直接调用tsc命令就可以了。

$ tsc

tsconfig.json的详细介绍,参见《tsconfig.json 配置文件》一章。

ts-node 模块

ts-node 是一个非官方的 npm 模块,可以直接运行 TypeScript 代码。

使用时,可以先全局安装它。

$ npm install -g ts-node

安装后,就可以直接运行 TypeScript 脚本。

$ ts-node script.ts

上面命令运行了 TypeScript 脚本script.ts,给出运行结果。

如果不安装 ts-node,也可以通过 npx 调用它来运行 TypeScript 脚本。

$ npx ts-node script.ts

上面命令中,npx会在线调用 ts-node,从而在不安装的情况下,运行script.ts

如果执行 ts-node 命令不带有任何参数,它会提供一个 TypeScript 的命令行 REPL 运行环境,你可以在这个环境中输入 TypeScript 代码,逐行执行。

$ ts-node
>

上面示例中,单独运行ts-node命令,会给出一个大于号,这就是 TypeScript 的 REPL 运行环境,可以逐行输入代码运行。

$ ts-node
> const twice = (x:string) => x + x;
> twice('abc')
'abcabc'
> 

上面示例中,在 TypeScript 命令行 REPL 环境中,先输入一个函数twice,然后调用该函数,就会得到结果。

要退出这个 REPL 环境,可以按下 Ctrl + d,或者输入.exit

如果只是想简单运行 TypeScript 代码看看结果,ts-node 不失为一个便捷的方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TypeScript 基础教程,适合新手 的相关文章

  • JavaScript - 无需布尔值即可运行一次

    有没有办法只运行一段JavaScript代码ONCE 而不使用布尔标志变量来记住它是否已经运行过 具体来说not就像是 var alreadyRan false function runOnce if alreadyRan return a
  • Javascript 在另一个函数中检测“Shift”键按下

    我正在从 Flash 影片 使用外部接口 调用我的 html 页面中的 Javascript 函数 并且我想知道调用该函数时用户是否按下了 Shift 键 例如 如果我通过鼠标单击调用该函数 这似乎很简单 因为我可以传递事件并检查 if e
  • 使用命名的成功/错误回调在 AngularJS 中声明一个 Promise

    我正在尝试做一些与 http 服务非常相似的事情 根据我的理解 http 返回一个 Promise 对象 使用它时 语法是 http success function data success callback error function
  • NestJS e2e 测试模拟会话装饰器

    我正在尝试使用 supertest 编写一个 e2e 测试 其中我的控制器实际上使用了 Session 装饰师 然而 我不想承担使用数据库连接等启动会话的全部负担 因此测试中的我的应用程序实际上并未初始化会话 相反 我想首先模拟掉装饰器提供
  • 递归修剪对象中所有元素的更好方法?

    如果我有一个像这样的物体 const obj field subfield innerObj a asdasd asdas innerArr s ssad innerArrObj b adsad 我想出了这样的东西 const trimFi
  • window.open:是否可以打开一个新窗口并修改其 DOM

    我想打开一个新窗口 var my window open iframe html blank height 600 width 600 但当我打开它时 我想修改它的DOM 我尝试过 var div my document createEle
  • 游戏手柄 JavaScript 未能按预期更新

    我正在尝试让浏览器报告我的 XBOX 控制器的状态 然而 在第一次按下按钮后 它似乎变得 卡住 我究竟做错了什么
  • html canvas动画卡顿

    谁能解释为什么提供的画布动画断断续续 我创建了一个测试存根来演示该问题 我在桌面上的 FF Chrome IE 以及 Android 上的 FF 和 Chrome 中看到了卡顿现象 口吃是由于垃圾收集造成的吗 似乎 raf 在每次调用时都会
  • JavaScript:常量属性

    在javascript中 我可以将对象的属性声明为常量吗 这是一个示例对象 var XU Cc Components classes or function aXU this Cc Components classes var XU new
  • 窗口大小调整触发的 DOM 事件

    我有一个布局相当复杂的页面 最初打开页面时 某些元素的对齐存在问题 但是 可以通过更改浏览器窗口的大小来 永久 解决此问题 显然 我不希望用户必须调整浏览器窗口的大小才能使页面正确显示 所以我想知道是否有一种方法可以在页面首次加载时以编程方
  • 带有 mkdocs 的本地 mathjax

    我想在无法访问互联网的计算机上使用 MathJax 和 Mkdocs 因此我不能只调用 Mathjax CDN Config mkdocs yml site name My Docs extra javascript javascripts
  • 如何知道浏览器空闲时间?

    如何跟踪浏览器空闲时间 我用的是IE8 我没有使用任何会话管理 也不想在服务器端处理它 这是纯 JavaScript 方法来跟踪空闲时间 并在达到一定限制时执行一些操作 var IDLE TIMEOUT 60 seconds var idl
  • 将 onclick 事件应用于页面加载时不存在的元素

    我将列表样式设置为看起来像选择框 并且当用户单击列表中的元素时我想触发一个函数 但是该元素是通过加载的AJAX因此 当页面加载并且我无法绑定时不存在onclick事件到它onDomReady 如果我把它作为一个普通的选择列表 我可以只标记一
  • Rails:找不到 JavaScript 运行时。有关可用运行时的列表,请参阅 https://github.com/sstephenson/execjs。 (ExecJS::运行时不可用)

    自从几周前 Dreamhost 升级了服务器以来 我的网站就被破坏了 我一直在努力解决它并取得了一些进展 但我仍然坚持希望是最后的问题 我在 Ruby 1 8 7 上使用 Rails 3 1 1 并收到来自 PhusionPassenger
  • 有没有办法伪造同步 XHR 请求?

    我正在使用 Emscripten 系统将一堆 C 代码移植到 Javascript C 代码有很多调用fopen这是一个同步 IO 调用 在 Emscripten 中 我们使用对本地资源的 XHR 请求来模拟这一点however 在 Fir
  • 如何使用 JavaScript 获取元素的填充值?

    我有一个textarea在我的 HTML 中 我需要获取整数或浮点形式的填充数值 以像素为单位 我如何使用 JavaScript 获取它 我没有使用 jQuery 所以我正在寻找纯 JavaScript 解决方案 这将返回padding l
  • 是否可以将请求标头添加到 CORS 预检请求中?

    我有一个从外部服务器 不是服务器 访问 API 的网站 为网站提供服务 通过简单的XmlHttpRequest 见下文 那个API 需要将用于访问服务的 API 密钥添加为请求标头 然而 正如这些CORS https developer m
  • Aurelia - 仅 HTML 自定义元素的内联定义

    我的 Aurelia 视图模型中有一个递归对象 如下所示 Class BottomlessPit Name string MorePits BottomlessPit null 因此 我想在 Aurelia 视图中使用递归模板 它只会在一个
  • Outlook 加载项,无法读取未定义的属性“BeginRequestEventArgs”

    我使用 Visual Studio 开发了 Outlook 插件 我的插件有一个按钮 用于填充会议邀请正文中的详细信息并添加所需的与会者 这在 99 的情况下都有效 但是 时不时地它会给我下面的 JavaScript 错误 Uncaught
  • D3 将现有 SVG 字符串(或元素)追加(插入)到 DIV

    我到处寻找这个问题的答案 并找到了一些我认为可能有用的资源 但最终没有让我找到答案 这里有一些 外部SVG http bl ocks org mbostock 1014829 嵌入SVG https stackoverflow com qu

随机推荐

  • 用opencv2的C api 给图片画矩形框

    使用opencv 3 4 6 Ubuntu系统 步骤 安装opencv 过程可以参考 https docs opencv org master d7 d9f tutorial linux install html 编程 opencv 3 4
  • 0基础也能看懂,软件测试怎么去介绍一个项目的测试流程?

    软件测试流程及规范 一 目标 制定完整且具体的测试路线和流程 为快速 高效和高质量的软件测试提供基础流程框架 最终目标是实现软件测试规范化 标准化 二 测试流程说明 三 需求分析 需求分析由SA制定 要求细化每一个功能的细节 每一个按钮的位
  • 华为OD机试真题-最大报酬【2023.Q1】

    题目内容 小明每周上班都会拿到自己的工作清单 工作清单内包含n项工作 每项工作都有对应的耗时时间 单位h 和报酬 工作的总报酬为所有已完成工作的报酬之和 那么请你帮小明安排一下工作 保证小明在指定的工作时间内工作收入最大化 输入描述 输入的
  • 基于c++的包装者模式初探。

    ifndef INPUTSTREAM H define INPUTSTREAM H class Inputstream public virtual void read 0 virtual Inputstream endif ifndef
  • TensorRT学习笔记--序列化(Serialize)和反序列化(Deserialize)

    目录 前言 1 序列化和反序列化的概念 2 代码实现 2 1 序列化并保存模型 2 2 反序列化加载模型 2 3 完整代码 前言 所有代码均基于 Tensor RT 8 2 5 版本 使用的是 Python 环境 1 序列化和反序列化的概念
  • 电路交换,报文交换与分组交换

    1 电路交换 由于电路交换在通信之前要在通信双方之间建立一条被双方独占的物理通路 由通信双方之间的交换设备和链路逐段连接而成 因而有以下优缺点 优点 由于通信线路为通信双方用户专用 数据直达 所以传输数据的时延非常小 通信双方之间的物理通路
  • Java开发环境不再需要配置classpath!

    前言 之前发布了关于java开发环境配置的文章 经过与网友的交流 我了解到在jdk1 5以后 java开发环境配置的时候 确实不需要对classpath进行配置 但市面上的书籍 以及一些博客 还是老一套 继续推荐配置classpath 并且
  • Jmeter 调用python3脚本

    前言 Jmeter 调用 Jython的Jar包 虽然可以执行python代码 但是只支持python2 7及2 7以下版本的 目前使用的都是py3 0以上的版本 所以放弃这种方法 解决方法 通过jmeter的BeanShell取样器 通过
  • websocket 简介

    一 WebSocket是html5新增加的一种通信协议 目前流行的浏览器都支持这个协议 例如Chrome Safrie Firefox Opera IE等等 对该协议支持最早的应该是chrome 从chrome12就已经开始支持 随着协议草
  • Centos7 修改主机名

    简介 在CentOS中 有三种定义的主机名 静态的 static 瞬态的 transient 和灵活的 pretty 静态主机名也称为内核主机名 是系统在启动时从 etc hostname自动初始化的主机名 瞬态主机名是在系统运行时临时分配
  • Windows+Ubuntu双系统下卸载Ubuntu

    记录一下自己卸载Ubuntu的步骤 防止以后再卸载重新找教程 1 删除Ubuntu的分区 步骤1 打开 我的电脑 选择 管理 点击 磁盘管理 步骤2 确定Ubuntu系统所在的磁盘分区 我的是磁盘1的磁盘分区6 7 8 9 然后一一删除 选
  • python每日一题_Python每日一题 001

    Talk is Cheap show me the code Linus Torvalds 将你的 QQ 头像 或者微博头像 右上角加上红色的数字 类似于微信未读信息数量那种提示效果 类似于图中效果 环境准备 安装PIL模块 Windows
  • MySQL之KEY分区和LINEAR KEY分区

    KEY分区 KEY分区与HASH分区相似 当然有不同点 1 在HASH分区中 可以使用整数列或者基于列值的表达式 即PARTITION BY HASH expr 而在KEY分区中 直接基于列 PARTITION BY KEY column
  • css清除默认样式

    清除默认样式 初始化样式 清除内外边距 margin 0 padding 0 自减盒子模型 box sizing border box ul ol 清除默认圆点 list style none a 取消下划线 text decoration
  • 华南x79 主板说明书下载_主板说明书找不到 机箱连线照样秒安装

    点击上方 电脑爱好者关注我们 小伙伴们在安装 升级电脑的时候 在主板上安装各种配件应该问题不大 但是连线呢 特别是机箱上那些细碎的小接口们 即使照着说明书都要琢磨半天 如果是老主板 一下子找不到说明书怎么办 这里小编就跟大家说一些简单的办法
  • windows上 nginx 配置好了access.log路径后,但是访问日志并没有记录

    windows 上配置 nginx access log 日志 1 问题 2 解决方案 2 1 为当前文件夹配置权限 3 结果 1 问题 之前 本机上配置了 nginx access log 日志 但是 并没有 记录 当时因为太忙了 就没有
  • 【Mybatis源码分析】动态标签的底层原理,DynamicSqlSource源码分析

    DynamicSqlSource 源码分析 一 DynamicSqlSource 源码分析 DynamicContext源码分析 SqlNode源码分析 动态SQL标签 Mybatis 动态SQL标签 举例 调试 SqlNode源码分析 M
  • Ubuntu/Linux下安装DosBox配置汇编环境

    Ubuntu Linux下安装DosBox配置汇编环境 微信关注公众号 夜寒信息 致力于为每一位用户免费提供更优质技术帮助与资源供给 感谢支持 一 首先我们去DosBox官网下载DosBox 0 73 或者直接启用终端命令行输入以下代码 s
  • leveldb深度剖析-查询流程

    至此 将插入流程以及压缩流程都已介绍完毕了 本篇主要介绍查询流程 一 查询流程 首先来看一下查询接口具体实现内容 查询 param options 查询选项 param key 查询key param value 输出参数 如果找到则赋值给
  • TypeScript 基础教程,适合新手

    TypeScript 基本用法 本章介绍 TypeScript 的一些最基本的语法和用法 最全教程 https tut qzxdp cn typescript 在线工具 https tools qzxdp cn 类型声明 TypeScrip