这是我参与8月更文挑战的第25天,活动详情查看:8月更文挑战
ts 的前世今生
- ts 的全称是 typescript,它是 javascript 的超集。
- ts 补充了 javascript 作为弱类型脚本语言的弱点,即增加了静态类型标注。
- ts 带来了某些 ECMAScript 提案中的特性与语法。
- ts 编译之后生成的是纯净的 JavaScript。
为什么使用 ts?
很多同事入门了 ts 之后,都大呼头痛。
明明上面定义了var o = {key: ''},下面在使用的时候 ts 就是说 o 中没有 key 属性~
明明可以用 o.key,ts 就是给一道红色的波浪线~
其实我们自己写的代码,我们当然知道其中的各种逻辑,但是代码真正运行的环境并不知道我们的逻辑,而恰恰我们的代码都是要靠机器来运行的
所以,往往有些时候写了一些 bug 我们却不自知,等到运行的时候看到报错才恍然大悟
ts 本身就是为了解决这种问题,尤其是在许多人参与的大型项目中,一个模块或者需求需要多个人参与其中的情景下,让别人理解我们的代码就变得非常重要。
而理解代码,并不是靠猜的。比如我有如下的函数:
function sum(a,b) {return a + b}
你看到的时候理所应当的认为 a 和 b 都应该是数字,这是一个求和的工具函数,然而,字符串也可以做加法的,比如:'1'+1的结果,是 11,而不是我们期待的 2。不幸这个错误只有在测试阶段才能测试出来,写代码的时候是看不出来的
这时候把代码改成 ts 的写法:
function sum(a: number, b: number) :number { return a + b}
当你调用sum('1', 1)的时候,ts 会立刻提示你这是错误的,sum 需要两个数字类型的参数。
ts 安装与使用
ts 全称是 typeScript,大家可以访问 ts 的中文网站学习,或者直接在官网学习。
安装:
使用 ts 需要安装 typeScript,因为 .ts 文件不能直接在浏览器中运行,所以我们写完以后,需要使用 typeScript 将其编译成正常的 .js 文件。
npm i -g typescript
安装以后可以查看安装的 typeScript 的版本
tsc -v
编译 ts 文件
写好的 ts 文件直接运行下面的命令,就可以在同级目录下生成编译好的 js 文件
tsc xxx.ts
我们新建一个 ts 文件,然后写下如下的代码,保存以后,运行编译
let name: string = 'Tom Hanse'
let isTrue: boolean = true
let number: number = 5
function(color: string){
console.log(color)
}
可以看到在同级的目录下生成了编译好的 js 文件,打开对比下
var s = 'Tom Hanse';
var isTrue = true;
var number = 5;
function a(color) {
console.log(color);
}
其实二者并没有什么明显的区别,唯一的不同点是 ts 中针对每一个变量,都标注了这个变量的具体类型,例如s:string说明 s 是一个字符串类型的值。
这个标注的功能其实就是注解。
ts 中的数据类型
ts 中也有一些数据类型,和 javascript 基本保持了一致,当然,ts 也相应的扩展了一些数据类型,作为补充来弥补 javascript 的不足
布尔类型
let flag: boolean = true
数值
let num: number = 1
字符串
let name: string = 'me, string!'
空与未定义
let n: null = null
let u: undefined = undefined
null 和 undefined 类型是所有类型的子类型,因此,可以将任何类型赋值为 null 或 undefined
let n: number = 4
n = undefined
let u:undefined
let m = u
空值
空值和 null、undefined 是不一样的,空值在 ts 中用 void 来表示,它代表没有任何返回值的函数
function reuturnNothing(): void{
let str: string = 'this function return nothing'
alert(str)
}
任意值
any 用来代表任意类型,可以访问 any 的任意属性和方法而不会被 ts 报错,而且任何操作的返回值都是任意类型。
因此很多人在代码里随意的使用 any ,把 typescript 硬生生的变成了 anyscript ,这是不可取的,也非常的不提倡。
let anything: any = 'Tom'
console.log(anything.myname)
console.log(anything.myname())
需要注意一点,如果一个变量在声明时未指定类型,且未被赋值,则默认为任意类型
数组
typescript 中定义数组有两种方式
let arr: number[] = [1,2,3]
let bookList: Array<string> = ['三体','三国演义']
其中的<string>叫做泛型变量,通常的默认表示方法是<T>
泛型
泛型可以在很大的程度上提升代码的重用性和通用性,有个最简单的例子来理解泛型: 在函数 a 中返回参数本身
function a (b: any): any{return b}
这样写不太理想,因为 any 是任意类型,我们要求返回参数本身,但是两个 any 类型不一定是一样的类型,如果定义成具体的类型,那可选择的范围就太大了,这时候,范型就有了用武之地
function a<T>(b:any): T{
return b
}
元组
元组类型表示一个已知元素数量和类型的数组,各元素的类型不必相同
let arr: [string, number, boolean]
arr = ['i love you', 3000, true]
如果访问元素越界了,则会使用联合类型进行替代,接着上面的代码
arr[3] = 'times'
arr[4] = false
Enum
枚举类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝等
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射,这可以用于反向查找:
console.log(Days["Sun"] === 0); // true
console.log(Days[0] === "Sun"); // true
也可以给枚举项手动赋值
enum Days {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};
console.log(Days["Sun"] === 7); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true
console.log(Days["Sat"] === 6); // true
never
表示的是那些永不存在的值的类型,如那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message)
}
// 推断的返回值类型为never
function fail() {
return error("Something failed")
}
// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
while (true) {}
}
object
表示非原始类型,也就是除 number,string,boolean,symbol,null 或 undefined 之外的类型
declare function create(o: object | null): void
create({ prop: 0 }) // OK
create(null) // OK
create(42) // Error
create('string') // Error
create(false) // Error
create(undefined) // Error