TypeScript 学习笔记(详细版)
一.初始
二.介绍 TypeScript
-
1.TypeScript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准(ES6 教程)。
-
2.TypeScript 由微软开发的自由和开源的编程语言。
-
3.TypeScript 设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何浏览器上。
-
4.2012年10月,微软发布了首个公开版本的TypeScript,2013年6月19日,在经历了一个预览版之后微软正式发布了正式版TypeScript
-
5.TypeScript的作者是安德斯·海尔斯伯格,C#的首席架构师。它是开源和跨平台的编程语言。
-
6.TypeScript扩展了JavaScript的语法,所以任何现有的JavaScript程序可以运行在TypeScript环境中。
-
7.TypeScript是为大型应用的开发而设计,并且可以编译为JavaScript。
-
8.TypeScript 是 JavaScript 的一个超集,主要提供了类型系统和对 ES6+ 的支持**,它由 Microsoft 开发,代码开源于 GitHub 上
三.我们为什么要学习 TypeScript?
编程语言按照数据类型大体可以分为两类,一类是静态类型语言,另一类是动态类型语言。
静态类型语言在编译时便已确定变量的类型,而动态类型语言的变量类型要到程序运行的时候,待变量被赋予某个值之后,才会具有某种类型。在 JavaScript 语言中,只有当我们对一个变量赋值时才会最终确定这个变量的数据类型,因此,JavaScript 是一门典型的动态类型语言。
动态类型的自由特性经常会导致错误,这些错误不仅会降低程序员的工作效率,而且还会由于增加新代码行,使得成本增加,最终开发陷入停顿。因为 JavaScript 无法合并类型以及编译时缺乏错误检查,因此,它不适合作为企业和大型代码库中服务器端代码。而 TypeScript 类型的定义和编译器的引入可以避免这些错误的出现。
一项研究表明,TypeScript 可以检测到所有 JavaScript 错误的 15%。在不严重破坏代码的情况下,开发人员可以更轻松地避免错误并进行代码重构。
总而言之,与 JavaScript 相比,TypeScript 代码更可靠、更容易重构。
显式类型使我们的代码可读性更高,所以我们的注意力将会更集中在系统究竟如何构建,以及系统的不同部分如何相互作用上。目前,JavaScript 已经成为了 Web 应用程序的主要开发语言,但是在大型复杂的 Web 应用系统中,JS 代码会显得杂乱无章难以梳理且调试困难,而 TypeScript 的类型定义使我们可以在大型、复杂的应用程序中,编写出更清晰的代码,源码的阅读也更容易更清晰。
同时,由于 JavaScript 是 TypeScript 的子集,因此可以在 TypeScript 代码中使用您想要的所有 JavaScript 库和代码。而且与其他语言不同,TypeScript 和 JavaScript 的语法并没有明显的区别,这就意味着你无需学习很多知识就可以开始无缝编写TypeScript 代码。
总结一下:
TypeScript 让我们的代码更可靠更清晰。
TypeScript 是 JavaScript 超集,完全兼容所有 JavaScript 语法规则。
四.TypeScript 的特点
TypeScript 主要有 3 大特点:
1.始于JavaScript,归于JavaScript
TypeScript 可以编译出纯净、 简洁的 JavaScript 代码,并且可以运行在任何浏览器上、Node.js 环境中和任何支持 ECMAScript 3(或更高版本)的JavaScript 引擎中。
2.强大的类型系统
类型系统允许 JavaScript 开发者在开发 JavaScript 应用程序时使用高效的开发工具和常用操作比如静态检查和代码重构。
3.先进的 JavaScript
TypeScript 提供最新的和不断发展的 JavaScript 特性,包括那些来自 2015 年的 ECMAScript 和未来的提案中的特性,比如异步功能和 Decorators,以帮助建立健壮的组件。
#总结
五.安装TypeScript
命令行运行如下命令,全局安装 TypeScript:
npm install -g typescript
安装完成后,在控制台运行如下命令,检查安装是否成功(3.x):
tsc -V
六.第一个 TypeScript 程序
编写 TS 程序
src/helloworld.ts
function greeter (person) {
return 'Hello, ' + person
}
let user = 'Yee'
console.log(greeter(user))
手动编译代码
我们使用了 .ts 扩展名,但是这段代码仅仅是 JavaScript 而已。
在命令行上,运行 TypeScript 编译器:
tsc helloworld.ts
输出结果为一个 helloworld.js 文件,它包含了和输入文件中相同的 JavsScript 代码。
在命令行上,通过 Node.js 运行这段代码:
node helloworld.js
控制台输出:
Hello, Yee
vscode自动编译
(1) 生成配置文件tsconfig.json
tsc --init
(2) 修改tsconfig.json配置
"outDir": "./js",
"strict": false,
(3) 启动监视任务:
终端 -> 运行任务 -> 监视tsconfig.json
类型注解
接下来让我们看看 TypeScript 工具带来的高级功能。 给 person 函数的参数添加 : string 类型注解,如下:
function greeter (person: string) {
return 'Hello, ' + person
}
let user = 'Yee'
console.log(greeter(user))
TypeScript 里的类型注解是一种轻量级的为函数或变量添加约束的方式。 在这个例子里,我们希望 greeter 函数接收一个字符串参数。 然后尝试把 greeter 的调用改成传入一个数组:
function greeter (person: string) {
return 'Hello, ' + person
}
let user = [0, 1, 2]
console.log(greeter(user))
重新编译,你会看到产生了一个错误:
error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'string'.
类似地,尝试删除 greeter 调用的所有参数。 TypeScript 会告诉你使用了非期望个数的参数调用了这个函数。 在这两种情况中,TypeScript提供了静态的代码分析,它可以分析代码结构和提供的类型注解。
要注意的是尽管有错误,greeter.js 文件还是被创建了。 就算你的代码里有错误,你仍然可以使用 TypeScript。但在这种情况下,TypeScript 会警告你代码可能不会按预期执行。
接口
什么是接口
接口定义
接口是对传入参数进行约束;或者对类里面的属性和方法进行声明和约束,实现这个接口的类必须实现该接口里面属性和方法;typescript中的接口用interface关键字定义。
在面向对象语言中,接口(Interfaces)是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类(classes)去实现(implement)。 TypeScript 中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。
接口作用
接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。typescrip中的接口类似于java,同时还增加了更灵活的接口类型,包括属性、函数、可索引和类等。
让我们继续扩展这个示例应用。这里我们使用接口来描述一个拥有 firstName 和 lastName 字段的对象。 在 TypeScript 里,只在两个类型内部的结构兼容,那么这两个类型就是兼容的。 这就允许我们在实现接口时候只要保证包含了接口要求的结构就可以,而不必明确地使用 implements 语句。
interface Person {
firstName: string
lastName: string
}
function greeter (person: Person) {
return 'Hello, ' + person.firstName + ' ' + person.lastName
}
let user = {
firstName: 'Yee',
lastName: 'Huang'
}
console.log(greeter(user))
简单的例子
interface Person {
name: string
age: number
}
let tom: Person = {
name: 'Tom',
age: 25
}
上面的例子中,我们定义了一个接口 Person,接着定义了一个变量 tom,它的类型是 Person。这样,我们就约束了 tom 的形状必须和接口 Person 一致。 接口一般首字母大写。有的编程语言中会建议接口的名称加上 I 前缀。 定义的变量比接口少了一些属性是不允许的:
interface Person {
name: string
age: number
}
let tom: Person = {
name: 'Tom'
}
多一些属性也是不允许的:
interface Person {
name: string
age: number
}
let tom: Person = {
name: 'Tom',
age: 25,
gender: 'male'
}
// Type '{ name: string age: number gender: string }' is not assignable to type 'Person'.
// Object literal may only specify known properties, and 'gender' does not exist in type 'Person'.
可见, 赋值的时候,变量的形状必须和接口的形状保持一致。
可选属性
有时我们希望不要完全匹配一个形状,那么可以用可选属性:
interface Person {
name: string
age?: number
}
let tom: Person = {
name: 'Tom'
}
interface Person {
name: string
age?: number
}
let tom: Person = {
name: 'Tom',
age: 25
}
这时仍然不允许添加未定义的属性:
interface Person {
name: string
age?: number
}
let tom: Person = {
name: 'Tom',
age: 25,
gender: 'male'
}
// Type '{ name: string age: number gender: string }' is not assignable to type 'Person'.
// Object literal may only specify known properties, and 'gender' does not exist in type 'Person'.
任意属性
有时候我们希望一个接口允许有任意的属性,可以使用如下方式:
interface Person {
name: string
age?: number
[propName: string]: any
}
let tom: Person =