介绍

TypeScript 是 JS 的严格超集,也就是说 JS 有的他都有,并且为我们新增了严格的静态类型检查还有现代化语言的一些特性。如果你学过 Java 这种强类型语言,那么 TypeScript 可以很快上手。

安装 & 环境初始化

首先我们需要安装 TypeScript

npm i typescript -g

然后开始构建一个项目

mkdir ts-study
cd ts-study
npm init
npm i lite-server --save-dev

接下来我们先创建一个 index.html 文件和 index.ts 文件,并且在 HTML 文件中引入 index.js,然后修改代码

// package.json 中在 scripts 中增加

"start": "lite-server"

// 在命令行中执行 tsc -init 创建 TS 配置文件

// 执行 npm run start

// 在 index.ts 输入以下代码

console.log('Hello world');
// 在命令行中执行 tsc -w 每次 ts 文件保存都会自动编译

// 然后在打开的网页中你应该可以看到 log 的 Hello world

到这一步,我们的 TS 环境已经跑起来了,如有问题请仔细核对步骤。接下来让我们先来学习 TS 的类型。

类型

接下来我们的代码都会写在 index.ts 中

Number & Bool

先让我们来看 number 类型

// 这个代码和我们的 JS 看起来没任何区别

// 但是在 TS 中只要你这样给变量赋值了

// 就代表接下来这个变量只能为 number 类型

let n = 1

n = '1' // => 会报错

// 以上赋值的代码,其实就等于

let n: number = 1 
// 但是如果你用上面的方式写代码,就叫做显式声明类型

// 第一句代码是隐式声明类型

n = 2.5 
// 不会报错,因为在 TS 中 number 类型为浮点型

接下来学习 bool 类型

let isDay = true

// 在 JS 中,除了 true,像很多对象或者 1 都可以代表 true

// 但是在 TS 中,布尔值就是布尔值,只有 true 和 false

isDay = 1 // 报错
数组 & 元组

先说数组,数组在 TS 中没什么变化

let arr = [1]
// 在定义一个数组类型变量的时候

// 我推荐使用显式声明类型的方式

// 因为数组中你不一定都会存储同一类型

// 例如以上代码,如果你想添加一个别的类型元素

// 就会报错,因为

let arr: number[] = [1]

// 如果你想该变量还可以存储字符串的话

let arr: (number | string)[] = [1]
arr.push('1')

再来讲讲元组。元组对于 JS 来说是个全新的类型,在这里你可以把它看做是一个固定顺序声明类型的数组,这个有点不大好理解,代码说明。

let tuple: [string, number] = [1] //error

let tuple: [string, number] = ['1'] //error

let tuple: [string, number] = [1, '1'] //error

let tuple: [string, number] = ['1', 1] //success

let tuple: [string, number] = ['1', 1, 1] //success

let tuple: [string, number] = ['1', 1, true] //error

// 从以上代码得出,元组显式声明了什么类型和长度

// 那么你元组相应的也必须是这个类型和大于等于该长度
枚举

这也是 JS 没有的类型,这个类型通常来说是为了解决魔法数字的痛点。

enum ServerCode {
  notFound = 404,
  success = 200

}
let code = ServerCode.success;
console.log(code);
switch (404) {
  case ServerCode.notFound:    
      console.log("404");    
      break;  
  case ServerCode.success:   
      console.log("200");    
      break;  
  default:   
      break;
}

对于枚举来说,如果你不给 notFound 赋值,那么 notFound 就是 0,接下来以此类推加一。

如果你给notFound 赋值为1,其他的类型都不赋值,那么第二个类型值就为 2,接下来以此类推加一。当然你可以还会遇到这种情况

enum ServerCode {
  notFound = 404,
  success = 200,
  a, // 201
  b = 300,
  c // 301

}
Any

这个类型基本不推荐在 TS 中使用,因为你一旦使用该类型,就少了 TS 的一大利器静态检查了。

// 一旦你这样声明变量,就会隐式声明为 any

let any

any = 1

any = true
函数

当然了,函数也是个类型

function hello(): void {    
    console.log('Hello'); // error
    // void 只能返回 undefined
    // 声明了什么类型就得返回什么类型
    return '1' 
}
// 对于函数来说,一般推荐参数声明类型

// 返回值会自动推断类型,不需要声明

// 当然你想写必然也是没毛病的

function sum(a: number, b: number) { 
   return a + b
}
// 当然了,如果你希望声明一个函数类型变量

let fun: (a: number, b: number) => number

// 当然以后只能这样赋值了

fun = sum // success

fun = hello // error

// 现在又有个需求,我需要声明10个这样类型的变量

let fun1: (a: number, b: number) => number

let fun2: (a: number, b: number) => number

let fun3: (a: number, b: number) => number

....
// 这样写类型就太累了,我们可以给类型取个别名

type sumType = (a: number, b: number) => number

// 然后你就可以这样写了

let fun1: sumTyp
Never

这是个 TS 2.0 时候加的新类型

function hello(): never {   
 throw Error('111')
}
// never 返回值类型指的是
// 永远不会执行完的函数或者没有返回值的函数
// 那么你可以觉得如下代码是返回 never 类型

function hello1(): never { 
   console.log('Hello'); //error

}
// 因为该代码他还是返回了 undefined

所以,如果你在想 Never 和 void 有什么区别的话。区别就是 void 代表返回 undefined,Never 代表函数不会执行完成,也不会返回任何值。

Non-Nullable

这也是 2.0 新增的一个类型,当然了,这个类型我们是声明不出来的。

还记得我们最开始生成的 tsconfig.json 文件不,你可以在该文件下找到 strictNullChecks 这个属性。这个属性默认值是 false, 这个属性的意思是说我们之前讲的那些类型,你都可以将他们赋值为 null 或者 undefined(除了 void),如果你将 strictNullChecks 设为 true,那么你就不可以将他们设置为 null 或者 undefined,除非你这样声明类型。