强类型与弱类型(类型安全维度)
语言层面限制
- 强类型:不允许任意的数据隐式类型转换
- 在编码阶段就能提示类型错误,可以更早暴露错误
- 可以提高代码效率和准确性(可以提供更准确的智能提示)
- 使重构更便捷可靠
- 可以减少不必要的类型判断
- 弱类型:允许任意的数据隐式类型转换
- 只能在代码运行阶段才能发现问题
- JavaScript是弱类型语言,Python是强类型语言
静态类型与动态类型(类型检查维度)
- 静态类型:变量类型在声明时确定,之后不允许再修改
- 动态类型:变量在运行阶段才能确定,且可以进行修改
- JavaScript是动态类型语言,Python是动态类型语言
解释型与编译型
- 解释型:代码运行时解析执行(脚本语言)
- 编译型:需要预先编译,再执行编译输出的可执行文件
JavaScript类型系统特征
JavaScript是动态类型 弱类型 解释型脚本语言
Flow
由Facebook于2014年推出的JavaScript的类型检查器
-
安装
yarn add flow-bin --dev
-
yarn flow init
初始化flow并生成配置文件.flowconfig
-
使用
- 在JS文件开头添加注释
//@flow
- 在相应的变量、参数后添加类型注解(冒号及类型)
- 执行
yarn flow
检查- 会启动后台服务监控JS文件
- 执行
yarn flow stop
停止后台服务
- 在JS文件开头添加注释
-
编译移除类型注解
-
flow-remove-types
-
yarn add flow-remove-types --dev
安装 -
yarn flow-remove-types src -d dist
指定路径输出编译移除后的JS文件
-
-
babel
yarn add @babel/core @babel/cli @babel/present-flow
安装-
添加配置文件.babelrc
{ "presents": ["@babel/present-flow"] }
yarn babel src -d dist
指定路径输出编译移除后的JS文件
-
-
开发工具插件
- VSCode插件:flow-language-support
- 其他IDE插件支持情况查看flow官网的编辑器支持
-
flow类型推断
- 可以根据代码实际使用情况自行推断变量的类型,而可以不指明类型注解
-
flow类型注解
- 在相应的变量、参数后添加冒号及类型
-
flow的类型
- 原始类型
- string
- number
- boolean
- null
- undefined
- 使用void表示
- symbol
- 数组类型
- Array<number>
- number []
- [string, number] :元组
- 对象类型
- { foo?: string, bar: number }
- 限制必须存在特定属性,并限定该属性的类型
- 属性名加问号,表示该属性可选,如果存在该属性,则属性类型必须为指定的类型
- { [string]: string }
- 限制对象key-value键值对类型,不限制属性数量
- { foo?: string, bar: number }
- 函数类型
- (string, number) => void
- 指定参数及返回值类型
- (string, number) => void
- 特殊类型
- 字面量类型:
a: 'foo' = 'foo'
- 限定变量值只能是特定值
- 联合类型:使用 | 分隔多个类型
- 字面量类型联合:
type: 'success' | 'warning' | 'danger' = 'success'
- 限定只能是特定可选值之一
- 类型联合:
a: string | number = 100
- 限定只能是可选类型之一
- 字面量类型联合:
- 类型别名
type StringNumber = string | number
a: StringNumber = 'string'
- maybe类型
- 类型前加问号
a: ?number = undefined
- 等同于
a: number | null | void
- 类型前加问号
- 字面量类型:
- Mixed与Any
- 可以接收任意类型
- Mixed:强类型
- 虽然可以接收任意类型,但是需要先明确变量是什么类型,才能进行相应的使用
- Any:弱类型
- 接收任意类型,并可以任意进行使用
- 主要为了用来兼容未进行强类型校验的老代码
- 原始类型
-
运行环境API
TypeScript
TypeScript是JavaScript的超集,在JavaScript基础上扩展了类型系统与ES6+新特性
-
优点:
- 类型系统使代码可靠性更高,同时可以使用ES6+新特性
- 兼容性好,可以在任何使用JavaScript开发的环境使用TypeScript
- 生态健全、完善
- 渐进式,可以只使用部分特性
-
缺点:
- 增加了很多概念,例如:接口、枚举、泛型
- 需要编写大量类型声明,对小型项目会增加开发成本
-
安装
yarn add typescript --dev
-
执行
-
yarn tsc typescript.ts
- 编译 typescript.ts 为 typescript.js 文件
- 进行类型检查
- 移除类型注解
- 转换ES6+语法为ES3语法
-
-
配置文件
-
yarn tsc --init
初始化创建配置文件 tsconfig.json - 配置项
- target
- 指定转换为什么版本的ES标准代码
- 不设置默认es3,配置文件默认es5,其他可选 es2015/es2016/es2017/...
- module
- 模块化标准
- 默认commonjs、其他可选 amd/umd/es2015/es2020/...
- sourceMap
- 源代码映射,生成sourceMap,便于代码调试
- outDir
- 指定编译结果输出目录
- 可以配置dist
- lib
- 指定标ts准库(ES对应版本内置对象的声明文件),接收一个数组
- target
-
-
rootDir
+ 指定代码根目录
+ 可以配置src
+ strict
+ 开启严格模式- 使用
yarn tsc
直接运行
- 使用
-
原始类型
- string
const a: string = 'hello'
- 非严格模式可以是null或undefined
- number
const b: number = 123
- 包含
NaN
Infinity
- 非严格模式可以是null或undefined
- boolean
const c: boolean = true
- 非严格模式可以是null或undefined
- void
const d: void = undefined
- 标记函数返回类型
- 非严格模式可以是null
- null
const e: null = null
- undefined
const f: undefined = undefined
- symbol
const g: symbol = Symbol()
- 需要配置target: es2015以上,或者配置lib引入es2015标准库
- string
-
强制使用中文显示错误消息
yarn tsc --locale zh-CN
- 修改VSCode setting中相关的配置
- 建议还是使用英文方式显示,便于问题查询定位
-
作用域问题
- 全局作用域下同名变量不能重复定义,可以放到函数作用域中,或者添加export {} 放到模块作用域下
-
Object类型
-
const foo: object = {} // [] // function() {}
可以接受数组、函数、对象 -
const obj: { name: string, value: number} = { name: 'hello', value: 123}
- 强制对象类型的声明,可以使用对象字面量
{}
的方式,同时可以限制允许出现的属性 - 使用接口定义更合适
- 强制对象类型的声明,可以使用对象字面量
-
-
数组类型
const array: Array<number> = [1, 2, 3]
const array: number[] = [1, 2, 3]
-
元组类型
- 元组是一种明确元素数量和类型的特殊数组
const tuple: [number, string] = [123, '456']
- 可以用来在一个函数中返回多个返回值
-
枚举类型
-
enum关键字定义枚举类型
enum Status { valid = 0, invalid }
枚举值使用等号=赋值
如果不指定枚举值,则默认从0开始,依次递增
如果指定枚举值为数字,则默认依次递增
如果指定一个枚举值为字符串,则需要指定
所有它之后的所有枚举的初始的值-
枚举类型会被编译为双向键值对对象,可以使用key获得value,也可以使用value获得key
var Status; (function (Status) { Status[Status["valid"] = 0] = "valid"; Status[Status["invalid"] = 1] = "invalid"; })(Status || (Status = {}));
enum关键字前增加const时为常量枚举,常量枚举不可以使用枚举值访问枚举的key
-
-
函数类型
-
函数声明形式
function say (name: string, value: number, ...rest: number[]) : string { return `hello ${name}` }
-
函数表达式形式
const said: (name: string, value: number, ...rest: number[]) => string = (name: string, value: number, ...rest: number[]): string => { return `hello ${name}` }
函数表达式将函数赋值给一个变量,需要给变量一个函数类型,使用箭头函数的形式
-
-
任意类型
- any类型
- 不会进行类型检查
- 用来兼容JS老代码
- 存在类型安全问题
- any类型
-
隐式类型推断
- 由typescript自行推断变量的类型
- 建议给每个变量添加明确的类型
-
类型断言
- 当typescript无法明确推断变量的类型时,可以使用as关键字告诉typescript变量是什么类型
- 也可以使用
<number>
尖括号<类型>的方式,但跟jsx混合使用的时候,会跟html标签混淆,建议使用as
-
接口
-
使用interface关键字定义接口,用来约束对象的结构
interface Post { name: string value: number desc?: string readonly url: string }
属性名后加问号,表示可选属性,可选属性外的其他属性必须存在
属性名前加readonly关键字,表示只读属性,初始化后不可修改
不能包含接口定义外的其他属性
-
-
类
面向对象编程中的概念,用来描述具体对象的抽象成员
ES6以前,使用构造函数+原型的方式实现面向对象的类与继承
ES6以后,提供了标准化的class来定义类
typescript增强了class的相关语法(访问修饰符、抽象类等)
-
基本使用
class关键字定一个一个类
-
在类中声明属性,并初始化(定义时赋值,或在构造函数constructor中初始化)
class Person { name: string age: number = 18 constructor(name: string, age: number) { this.name = name } }
-
访问修饰符
控制类中属性和方法的访问级别
- public: 默认
- private: 无法被类的实例访问
- 如果constructor被private修饰,将不能使用new实例化
- protected: 无法被类的实例访问,可以在子类中访问
-
只读属性
- readonly关键字修饰类的属性
- 只能在定义或者构造函数中初始化,之后不能被修改
-
类与接口
同样使用interface定义接口
在interface中定义类的方法,但不提供实现
-
class使用implements关键字实现一个或多个接口,必须包含接口中定义的方法的实现
interface Eat { eat(food: string): void } interface Run { run(speed: number): void } class Dog implements Eat, Run { eat(food: string) { console.log(food) } run(speed: number) { console.log(speed) } }
-
抽象类
-
使用abstract关键字定义抽象类
- 抽象类不能被new实例化,只能被继承
-
使用abstract关键字定义抽象类的抽象方法
- 抽象方法不能具有实现
- 子类继承后必须实现抽象方法
abstract class Animal { eat(food: string): void { console.log(food) } abstract run(speed: number): void } class Cat extends Animal { run(speed: number): void { } } const cat = new Cat() cat.eat('food')
-
-
泛型
函数定义后使用<T>定义泛型,参数的类型可以被指定为T
-
函数使用时在函数名后使用<类型>指明具体的类型,以此使函数在使用时可以传入不同类型的参数
function hey<T>(value: T) { console.log(value) } hey<string>('123') hey<number>(123)
-
类型声明
- declare关键字进行类型声明
- 使用第三方库时,如果没有提供类型声明文件,需要安装相应的类型声明模块
- 类型声明模块应该是开发依赖
-