持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
本文是ts系列第一篇,是总结自己在学习和工作中使用ts的心得感想,仅作为自己复习使用,如对您有启发不胜荣幸。
ts 定义
ts 是 javascript 的超集合,类似于 es6 与 es5 的关系,es6 兼容了 es5 的所有语法,但是在es5 的基础上进行了扩展。ts有如下几个特点:
静态类型 vs 动态类型
// demo.js
let a = '123'
a = 123
// demo.ts
let a = 123
a = '123' // 报错
在demo.ts文件中,已经声明了a,并赋值为数字,那么a 默认的类型是数字类型,接着又给a赋值了字符串,改变了a的类型,所以会报错。
ts有一个类型断言的功能,如果你设置的值的类型非常明确,其实没有必要写类型,让ts帮我们来推断即可。
对静态类型的深度理解:如果给一个变量定义某个类型,那么这个变量不仅仅是这个类型,而是这个变量也具备了这个类型所带有的属性和方法。如果定义一个变量不给其定义类型,那么就无法获得属性和方法。如下图,可以看到output这个字符串类型所带有的所有的属性和方法。
可以看到,当我定义了 str 变量为字符串类型的时候,那么就相当于这个变量拥有了字符串类型带有的所有属性和方法。
TS 最终编译为 JS
TS 只是开发环境的工具,构建之后产出 JS 在浏览器运行。
ts的优势
- 发现潜在bug ts的静态类型让我们在开发过程中,可以发现潜在的bug。比如下面这段代码,demo没有传递参数,在编辑器ts就会帮我们指出来,如果这段代码用js写,编辑器不会帮我们指出来,只会在编译运行的时候报错。
- 代码提示更加友好
- 代码语义更加清晰易懂,可以更好的阅读代码
比如当你看到上面图中函数 data 这个参数的时候,就知道它有x和y这两个属性。如果用js写,我还要进入到 data 这个对象里面看,才能看清楚。如果ts里面定义的好的话,基本不用写注释。
ts的编译配置安装
- 安装ts
npm install -g typescript
- 查看版本
tsc -v
- 运行,把ts文件转化成js文件
tsc index.ts
- 创建ts的配置文件tsconfig.json
tsc --init
如果你觉得还需要把ts编译成js文件才能执行很麻烦的话,你可以安装:
npm install -g ts-node
但是安装之后还不够,需要安装node的类型文件,如果不安装会报错,这是因为 TypeScript 自带的类型只有 DOM 环境里面的那些类型(在 lib.dom.d.ts 里面),Node.js 的类型是不自带并且通过 @types/node 这个库来维护的。
npm install @types/node
ts 常用类型
基础类型
let m: number = 123
let str: string = '123'
let boo: boolean = false
类型断言: ts就会断言a是number类型,有时候如果值的类型非常明确,其实没有必要写类型,让ts帮我们来推断即可。
let a = 100
或
let x: number | string | boolean = false
any
let y: any = []
在开发中尽量避免使用any,因为ts最重要的特点是设定变量的类型,如果都是any,那就是anyScript了,而不是typeScript了。
数组
两种写法
let arr: number[] = [1, 2]
let arr1: Array<string> = ['1', '2']
元组
当你知道一个数组的长度且固定,知道每个元素的类型且固定,那么就可以变成一个元组来管理,而不用数组来管理。元组主要是用在处理excel,csv文件的时候用
let arr2: Array<string | number | boolean> = [1, '2', false]
枚举
下面的代码其实你不知道0, 1, 2所代表的意思的,所以就出现了枚举。
function getResult(status) {
if (status === 0) {
return 'offline';
} else if (status === 1) {
return 'online';
} else if (status === 2) {
return 'deleted';
}
}
enum Status {
OFFLINE,
ONLINE,
DELETED
}
// 上面的枚举代码等同于下面的这个对象
const Status = {
OFFLINE: 0,
ONLINE: 1,
DELETED: 2
}
function getResult(status) {
if (status === Status.OFFLINE) {
return 'offline';
} else if (status === Status.ONLINE) {
return 'online';
} else if (status === Status.DELETED) {
return 'deleted';
}
return 'error';
}
const result = getResult(Status.OFFLINE);
对象
对象的类型是object
let obj: object = { x: 10 }
我们一般很少使用object,因为它无法定义对象里面的属性,它非常抽象,一般会用 interface 或 class 代替。
函数
函数的类型是Function
let fn: Function = () => {}
同样,我们也很少使用Funtion,因为你无法定义函数的参数和返回结果,太抽象了,一般用自定义 type 代替。
type: 自定义类型
自定义了一个类型infoType,这个类型即是string 也是 number
type infoType = string | number
自定义一个函数类型,上面Funciton类型无法定义函数里面的细节,这里使用type可以定义函数的细节
type fnType = (x: number, y: number) => void
const fn2: fnType = (a: number, b: number): void => {}
interface 接口
接口: 一些类型的集合
interface IPerson {
name: string
age: number
fn1: fnType
}
const person1: IPerson = {
name: 'zhangsan',
age: 20,
fn1: (x: number, b: number) => {}
}
在工作中,一般使用interface 来代替object类型
tips: 1. 接口没有等号,直接接{}; 2. 属性后面没有逗号
class 类
接口还可以用在 class 中
class Person implements IPerson {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
fn1(a: number, b: number): void {}
}