出现原因
编程的时候,我们有一个共识: 就是错误越早被发现越好
- 能在编写代码的时候被发现,就不要在编译阶段被发现(也就是能主动避免错误就不要让IDE来提示我们错误)
- 能在编译阶段的时候发现错误,就不要在运行阶段发现错误
- 能在开发时候发现的错误,就不要在测试的时候发现
- 能在测试的时候发现的错误,就不要在运行的时候被发现
js存在一个弊端:没有类型检测
// JS在调用的时候,并不会对传入的参数进行任何的校验
// 1. 不会进行参数类型的校验 (无论传入的参数是不是具有length属性)
// 2. 不会判断是否有传入参数 (运行的时候可能根本就没有任何的参数)
/*
由于js并不会对上述内容进行调用,所以如果我们希望避免错误的发生
我们需要手动对传入的参数的个数和类型添加校验代码
*/
function getLength(v) {
console.log(v.length)
}
// 正常调用
getLength('Hello TypeScript')
getLength([1, 2, 3])
// 异常调用
getLength(123)
getLength()
// 如果js出现了错误,那么后续的代码就无法正常执行
// 所以js很可能因为没有类型约束而导致系统崩溃
// 后续代码 。。。。
如果此时我们需要为js传入的参数添加相关的限制,并且在编译阶段就发现对应的错误,以便于改正
在上述案例中:
- 设置getLength函数的参数v是必传属性
- 设置v必须是数组,字符串等有length属性的值
但是js无法在编译阶段发现上述问题,只能在运行阶段才能发现这些问题,此时很有可能代码已经交给了用户。
类型约束方案
创建的类型约束有:
2014年, Facebook提出的Flow,(vue2.x所使用的类型校验方案)
2014年,Microsoft提出的TypeScript (Vue3.x所使用的类型校验方案)
这里以TypeScript为主
简介
TypeScript 是
拥有类型的JS超集,它可以被编译为原生JS代码
-
TS是加强版的JS, 是JS的超集,完全支持原生的JS代码(包括最新的ES6,ES2021等代码)
并在原生JS的语法上进行了扩展(如类型注解,枚举,元组等)
-
TS无法在浏览器上直接运行,所以TS需要先编译为原生的JS后才可以运行在浏览器上,TS默认会将代码编译为ES3的代码,也可以修改配置,使其编译成ES5或ES6的代码
2.1 常见的TS解析工具:
- tsc (typescript compiler)--- ts官方提供的在命令行中解析ts的工具
- ts-loader --- webpack中解析ts的loader
- Babel --- 配置preset(preset是多个plugin的合集) --- @babel/preset-typescript
初体验
# 全局安装typescript,以便于在全局可以使用命令tsc
$ npm i typescript -g
# 查看tsc版本
$ tsc --version
# 编译
$ tsc <ts文件>
# 实时编译
$ tsc -w <ts文件>
# 只进行类型校验,但是不生成编译后的js文件
$ tsc <源文件名或文件夹名> --noEmit
index.ts
let msg: string = 'Hello TS'
msg = 123 // => error
function getLength(v: string): number {
return v.length
}
getLength('Klaus')
getLength(123) // => errro
// tips: 默认配置下,即使ts在编译的时候报错了,但是ts依旧可以成功被转换为js代码, 但是这段js代码在运行的时候,可能会出现错误。如果希望ts出现错误的时候,ts无法编译为js,需要修改ts的默认配置
环境搭建
搭建环境自动编译ts,并运行
ts-node
# ts-node 是一个工具库,可以解析ts文件,并直接在node环境下运行ts代码
$ npm i ts-node -g # 全局出现指令 ts-node
$ npm i @types/node tslib -g # ts-node所依赖的库 tslib -- ts的工具函数库 @types/node -- node针对于ts的类型定义
# 使用
$ ts-node foo.ts
在webpack中集成
# 安装
$ npm i ts-loader typescript webpack webpack-cli -D
$ npm i html-webpack-plugin webpack-dev-server -D
webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/index.ts',
mode: 'development',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
/*
ts中禁止我们使用带上ts后缀名的方式引入ts文件
例如: import { foo } from './utils/foo.ts'
但是如果去掉后缀名.ts的时候,webpack无法自动识别到对应的文件
所以此时需要修改webpack的后缀识别配置,让webpack可以自动识别到ts后缀文件
使import { foo } from './utils/foo'可以成功执行
*/
resolve: {
// 如果设置了扩展,默认的扩展配置会被覆盖
// 所以需要加上原有的默认配置
// 因为别的插件(如webpack-dev-server)在进行工作的时候,其内部代码在运行的时候是需要原本的默认配置的
extensions: ['.ts', '.js', '.json']
},
module: {
rules: [
{
test: /\.ts$/,
loader: 'ts-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html'
})
]
}
TS初体验
// 变量的声明
// var|let|const 标识符: 类型名称 = 值
let num: number = 123
// :number -> 类型注解
/*
number 和 Number区别
number => 数值类型
Number => 数值的包装类 类型
*/
let num1: number = 321
let num2: Number = 321
// 类型推断 | 类型推导
// 如果在定义的时候直接赋值
// 此时会将值的类型自动作为标识符的类型,这个过程就被称之为类型推断或类型推导
let str = 'Klaus'
// str = 123 => error