管什么真理无穷, 进一寸有一寸的欢喜
一、类型系统
1. 强类型、弱类型(类型安全)
- 强类型: 在语言层面限制了,函数的实参类型和形参类型必须一致
- 弱类型: 在语言层面不会限制实参类型
- 强类型中,不允许任意的隐形类型转换
2. 静态类型、动态类型(类型检查)
- 静态类型: 一个变量,声明时他的类型就是明确的,声明过后,他的类型就不允许再修改
- 动态类型: 运行阶段才能明确变量类型,变量的类型随时可以改变
- 静态类型语言中的变量是没有类型的,变量中存放的值是有类型的
3. JavaScript 类型系统特征
- JavaScript 是一门弱类型 / 动态类型的语言
- 源于早期 JS 语言只是为了解决简单应用
- JS 是一种脚本语言,没有编译环节,静态类型会在编译时做类型检查
4. 弱类型的问题
- 只有在运行后,才能发现类型问题
- 类型不确定会导致执行结果不符合的隐患
- 传入的参数可能会被自动转换了类型
5. 强类型的优势
- 错误更早暴露: 编码阶段就可以提示错误
- 代码更智能,编码更准确
- 重构更可靠
- 减少不必要的类型判断
二、Flow 静态类型检查器
1. Flow概述
认识 JS 静态类型检查工具 Flow
function sum(a: number, b: number) {
return a + b
}
VScode 配置:
Code => 首选项 => 设置 => 搜索:javascript validate => 关闭 JavaScript 校验
2. Flow 基础用法
⑴. 安装 flow
npm init -y
// 目录下新增了一个 `package.json` 的文件
npm i flow-bin --dev
// 目录下已经安装好了 flow,并且可以看到依赖包:node_modules、package-lock.json
⑵. 编辑 package.json
"scripts": {
...
"flow": "flow"
},
⑶. 初始化flow
npm run flow init
// 目录下会新增一个 `.flowconfig` 文件
⑷. 新建测试文件
目录下新增一个测试 ts 文件:
@flow 标识才能够被 flow 捕获到
const sum = (a:number, b:number) => a + b
sum(1, '2')
如果提示 js 语法校验,需要手动关闭(如上图)
设置 -> javascript valida -> 关闭JavaScript验证
⑸. 运行 flow
npm run flow
// => No errors! (并没有报错,不符合预期)
// 如果并没有报错,那就执行下面的停止 flow,然后再次启动 flow 即可
⑹. 停止 flow
// 关闭 flow
npm run flow stop
⑺. 展示
3. 编译移除注解
添加了类型注解的文件不能运行,所以需要在编译过程中移除类型注解
⑴. 安装
// 安装 移除插件
npm add flow-remove-types
⑵. 编辑 package.json
"scripts": {
...
// src 是博主的文件目录,如果直接在当前目录,改为`src/` => `./`
"flowRemove": "flow-remove-types src/ -d dist/"
},
4. Bable:编译移除注解 - 方案 2
⑴. 安装
// 安装(博主安装失败了—_-)
npm i @babel/core @babel/cli @babel/perset-flow --dev
⑵. 编辑 .babelrc
{
"presets": ["@babel/preset-flow"]
}
⑶. 编辑 package.json
"scripts": {
...
"babel": "babel src/ -d dist/"
}
⑷. 运行 babel
npm run babel
5. Flow 开发工具插件:编译移除注解 - 方案 3
VScode 自带插件Flow language Support
二、Flow 用法
1. 类型推断
function square(n) {
return n * n;
}
square('100')
不写类型注解,但是通过计算的过程,flow 会类型推断,并提醒
=> 无法执行算术运算,因为字符串[1]不是数字
2. 类型注解
三种类型注解:函数参数、变量名、函数返回值
function square(a: number) {
return a * a
}
let num:number = 100
function foo():number {
return 100
}
3. 数据类型
⑴. 原始数据类型
JavaScript 的七种原始数据类型: String、Boolean、Number、Null、Undefined、Symbol、以及 ES6 新增的Symbol、BigInt
let str: string = 'string'
let num: number = Infinity
let a: boolean = true
let b: null = null
let c: void = undefined
let d: symbol = Symbol()
⑵. 数组数据类型
指定数组内,每一个元素的数据类型
const arr:Array<number> = [1, 2, 3]
const arr2: number[] = [2, 3, 4]
const arr3: [string, number, number] = ['1', 2, 3]
⑶. 对象数据类型
指定对象的数据类型,和字面量语法非常类似
const obj1: { name: string; age: number } = {
name: "zoe",
age: 18,
}
const obj2: { name: string; age: number; sex?: 0 } = {
name: "zoe",
age: 18,
}
const obj3: { [string]: number } = {}
obj3.key1 = "sex"
obj3.key2 = 0
⑷. 函数数据类型
函数参数类型、返回值类型
function foo(callback: (string, number) => void) {
callback("string", 100);
}
⑸. 特殊数据类型
const a: 'foo' = 'foo'
const type: 'success' | 'warning' | 'danger' = 'success'
const b: string | number = 100
type stringOrNumber = string | number
const c: stringOrNumber = 'string'
const gender: ?number = undefined
⑹. Mixed 和 Any
Mixed: 所有类型的联合类型(string | number | boolean …)
Any: Any 和 Mixed 作用相同,但 Mixed 仍是强类型,而 Any 是弱类型
4. 运行环境 API
const element: HTMLElement | null = document.getElementById('app')
不同文件对应的 API 有类型限制,通过右键 HTMLElement 即可查看类型的声明文件
四、TypeScript 语法规范和使用
1. 概述
TypeScript 是基于 JavaScript 基础之上的编程语言,超集/扩展集(superset)
- 扩展的主要是更为强大的类型系统,以及对
ECMAScript 的新特性支持
- 已经成为前端的第二门语言
2. 基础配置
⑴. 安装 TypeScript
// 全局安装
npm install -g typescript
// 查看版本
npm tsc --v
示例:
const hello = (name: string) => {
console.log(`Hello, ${name}`)
}
hello('TypeScript')
⑵. 配置文件
编译项目,生成一个配置文件tsconfig.json
npm tsc --init
tsconfig.json 配置文件注解
{
"compilerOptions": {
// 设置编译后的javascript采用的ECMAScript标准
"target": "es5",
...
// 输出的代码使用什么方式进行模块化,这里用的是commonJS,会把输入输出弄成require和module.export的方式
"module": "commonjs",
// 设置编译结果输出的文件夹
"outDir": "dist",
/* Redirect output structure to the directory. */
// 源代码ts文件所在的文件夹
"rootDir": "src",
/* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
/*类型检查相关 Strict Type-Checking Options */
// 开启严格模式,对类型检查十分严格
// 例如:any类型,也要严格写出来
"strict": true,
/* Enable all strict type-checking options. */
}
⑶. 原始类型
let a: string = "string"
let b: boolean = false
let c: number = 100
let d: null = null
let e: void = undefined
let f: undefined = undefined
let g:symbol = Symbol()
⑷. 标准库声明
内置对象所引用的声明文件
上节中看到的 Symbol 会报错,给出的提示是需要更高版本的声明文件,而 Symbol 是 ES6 新增的数据类型,右键查看定义
这里博主用的是,ES2019 版本(左上角文件名称),所以包含了 Symbol 的类型声明,就不会报错了
解决 Symbol 报错的方法:
- 需要将配置文件中的
target 改为es2015
- 不改target,将
lib 选项改为[“ES2015”]
- 其他文件的,
console 的定义会报错,默认引用的DOM类库被覆盖,在配置文件中加上"DOM",这里的DOM是包含了DOM+BOM
⑸. TS 的中文报错设置
首选项 => 设置 => 搜索 TypeScript locale => 设置 zh-CN
(不过不建议这样使用,因为不利于报错的检索)
⑹. 作用域问题
当在文件中,定义了其他文件的重名变量时
解决作用域问题:
const a: number = 100;
(function () {
const a: number = 100
})()
export { }
3. 数据类型
⑴. 对象数据类型
|