入门
TS入门是比较简单的,后面学习曲线会越来越陡峭,无论类型推导,还是面向对象,都是需要投入非常大精力学习的。
本节主要讲解ts入门必须要掌握的4个点。
- 转译
- 超集
- 类型添加擦除
- 如何运行
转译
编译和转译是2个概念。
- 编译(Compilation)是指将高级语言(如Java、C++等)编写的代码转换为机器语言(二进制代码)的过程。
- 转译(Transpilation)是指将一种编程语言的代码转换为另一种编程语言的代码的过程。
编译和转译的目的都是将源代码转换为目标代码,但它们的输出结果和使用场景有所不同。编译通常用于将高级语言转换为机器码,以便在特定的硬件平台上直接运行。转译则更多地用于将一种编程语言转换为另一种编程语言,以便在不同的环境或浏览器中运行。
js世界历来有转译的传统,被吐槽最多的就是Brendan Eich用了10天写出来的玩具语言,你可以非常轻松的在Chrome Devtools里折腾出很多神奇的bug。另外,作为脚本语言,它其实也不是很严格,各种规范也是很混乱,比如JScript,ActionScript等曾经就都是让人分不清楚的。
到现代Web开发,从coffeescript(类Ruby)到Cappuccino(类Objective-c)到rescript(类OCaml语法),到typescript都是转译的思路。最神奇的竟然是es规范发展太快,于是诞生了Babel.js这样的现代js转译。除了转译规范,移除类型,啥也不干。
Typescript做的主要的事儿就4件
- 增加类型,这是babel没有的。
- babel超集,可以说babel支持的它基本都支持,包含很多es新特性。
- 部分增强,比如interface,这是babel没有的。
- 转译时擦除类型,比如
type
和interface一样,在编译时,会被抹除。
超集
JavaScript很容易学习,而TypeScript的学习曲线较陡,需要事先有脚本编程知识。 JavaScript是一种脚本语言,而TypeScript是一种面向对象的编程语言。 TypeScript支持模块,而JavaScript不支持。 TypeScript支持静态类型,可以在编译时检查正确的类型,而JavaScript不支持。 TypeScript代码必须编译,但编译JavaScript是不必要的。 TypeScript支持可选参数函数,而JavaScript不支持。 JavaScript有一个庞大的开发者社区,而TypeScript没有。
类型添加与擦除
对于一门语言来说,肯定离不开基本数据类型和自定义类型。ts提供了一系列的关键字作为特殊类型代号,其他的都好说,唯一让我有点兴趣的是联合类型
,这非常有趣的一个特性。
typeof
关键字用于判断是否是某种类型string
表明是字符串类型,它不同于Java,首字母是小写boolean
和Boolean
类型是不同的number
直接表示数字类型,没有那么多麻烦的精度问题(0b、0O、0x指明进制问题)any
是万能类型,相当于Java中的Object,全部是any相当于是普通js。所以,如果你恨ts,就可以一路any到天明never
表示那些永不存在的值类型object
表示非原始类型,和Java中的不太一样string | number
类似这样的是联合类型,这也是非常神奇的一点。这里只允许这两种类型的转换,并且能调用的方法,要取两者交集- `` 之间的字符串可以使用类似shell的语法,做模版
${}
readonly
这竟然是个关键字,表明只读属性[propName: string]: any;
这一行代码值得研究,但不推荐这么做number[]
数组和Java类似,不过这是声明后置的语法,值使用[]声明,而不是{}function
函数和javascript的没什么区别,有两种声明方式。lambda对js来说肯定是强项=>
的语法也比较恶心人,和ES6联合起来可以写一大篇文章...rest
注意这个东西!类似Java中变参的意思as
是一个关键字,我们可以理解为Java的cast
,但它也仅仅是语法检查而已,运行时并无法控制。(window as any)
很酷,但容易出错
由于js是一门弱类型的语言,有很多的运行时转换,就不能使用类似于Java一样的强类型转换方式,所以typescript
可以在编译阶段通过语言特性增强一些类型检查的功能。而在运行时,大多数根本就没有这样的判断,所以ts更像是一个过程工具。
那么反过来想想呢?
如何运行
1、内置runtime
<script src="https://unpkg.com/typescript@4.9/lib/typescriptServices.js"></script>
<script>
const tsCode = 'let num: number = 123;';
const jsCode = window.ts.transpile(tsCode);
document.write(jsCode);
</script>
另外一个做法
有了这个环境分离基础,那么就可以实现在浏览器端运行 ts compiler!因为 ts compiler 本身编译后也是 js,只需要提供一个浏览器端的 compilerHost 就可以,typescript 官方提供了一个虚拟文件服务包@typescript/vfs 提供浏览器端兼容的 fs 服务
import ts from 'typescript'
import tsvfs from '@typescript/vfs' // 虚拟文件服务
import lzstring from 'lz-string' // 一个压缩算法
// 从cdn创建上下文,包含了ts lib的类型库,从cdn拉取
const fsMap = await tsvfs.createDefaultMapFromCDN(
compilerOptions,
ts.version,
true,
ts,
lzstring
)
// 可以设置一个虚拟的文件,文件名index.ts,文件内容第二个参数
fsMap.set('index.ts', '/** typescript 代码 **/')
const system = tsvfs.createSystem(fsMap)
// host是ts编译器将文件操作隔离出来的部分
// 这里可以创建一个虚拟的文件服务,不依赖nodejs,在浏览器中可用
const host = tsvfs.createVirtualCompilerHost(system, compilerOptions, ts)
// 创建编译程序
const program = ts.createProgram({
rootNames: [...fsMap.keys()],
options: compilerOptions,
host: host.compilerHost,
})
官方的Playground其实就是这种原理。
2、转译成js后执行
通过编译器编译
$ npm install -g typescript
$ tsc hello.ts
通过代码
const { outputText } = ts.transpileModule(your_ts_code, {
compilerOptions: {
strict: false,
sourceMap: false,
// 其他编译选项
}
});