类型系统相关介绍
类型安全
- 强类型
- 语言层面限制函数的实参类型必须与形参类型相同
- 语言中不允许任意的隐式类型转换
- 弱类型
- 语言层面不会限制实参的类型
- 语言中允许任意的隐式类型转换
类型检查
- 静态类型
- 声明时,变量的类型便是明确的
- 声明后,变量的类型就不允许再修改
- 动态类型
- 在运行阶段,才能够明确类型变量
- 变量的类型可以随时发生变化
- 可理解为,动态类型的变量是没有类型的,而变量的值是有类型的
强类型语言优势
- 错误更早暴露
- 代码更智能,编码更准确
- 重构更牢靠
- 减少不必要的类型判断
TypeScript
安装
yarn add typescript --dev
初始化
yarn tsc --init
配置
// tsconfig.json
"target": "es5" // 编译转化后的语言版本
"module": "commonjs" // 编译模块化方式配置
"outDir": "dist" // 编译后文件的输出路径
"rootDir": "src" // 编译的源文件路径
"sourceMap": true // 开启源代码映射
"strict": true // 开启严格模式
"lib": ["es2015", "DOM"] // 标准库,添加标准库,使得编译能够识别新的语法和模式
编译
yarn tsc fileName.ts
设置中文输出报错消息
yarn tsc --locale zh-CN
原始数据类型类型控制
// 非严格模式下,string|number|boolean 可以是 null
const a: string = ''
const b: number = 100 // NaN // Infinity
const c: boolean = false // true
// 严格模式下只能是 undefined;非严格模式则二者皆可
const d: void = undefined
const e: null = null
const f: undefined = undefined
const h: symbol = Symbol()
Object 类型(泛指所有非原始类型的数据类型)的类型控制
const foo: object = function () {} // [] // {}
数组类型
const arr1: Array<number> = [1, 2, 3]
const arr2: number[] = [1, 2, 3]
元组(Tuple)的类型控制
const tuple: [string, number] = ['foo', 100]
枚举类型的类型控制
- 如果没有设置默认值,则会默认第一项为 0,往后各项默认 +1
- 如果只设置了前面的部分项,则往后的没有设置默认值的项也会默认 +1
- 当有项设置默认值为字符串类型时,则需要手动添加默认值
- 在枚举类型前添加常量声明 const 可以使得在编译时默认转化为常量,从而避免枚举类型穿透到编译结果文件中
const enum PostStatus {
Draft = 0,
Unpublished = 1,
Published = 2
}
const post = { title: '', content: '', status: PostStatus.Draft }
函数类型的类型控制
function fun1 (a: number, b?:number = 18, ...rest: number[]): string {
return 'fun1'
}
func1(100, 200)
func1(100)
func1(100, 200, 300)
任意类型的类型控制
function stringify (value: any) {
return JSON.stringify(value)
}
隐式类型推断
当变量声明时没有设置类型,typescript 会依据变量后续的使用进行类型推断。
类型断言
在编写时,告知 typescript 某一个函数或者接口返回的数据类型
接口
- TypeScript 中,通过 interface 来声明接口
- 接口的作用,在于设置、规定一个对象的属性以及属性值的类型
interface Post {
title: string
subTitle?: string // 可选成员
content: string
readonly summary: string // 只读成员
}
function printPost(post: Post) {}
printPost({title: '', content: '', summary: ''})
类
class Person {
// init
public name: string // 访问修饰符,表公用属性,为默认属性,可不加
private age: number // 访问修饰符,表私有属性,即只能在类的内部进行访问
protected gender: boolean // 保护属性,也不能在类的外部进行访问,但可以在子类中进行访问
readonly sex: string // 只读属性,初始化之后不允许再次修改
constructor (name: string, age: number) {
this.name = name
this.age = age
}
sayHi (msg: string): void {
console.log(`I am ${this.name}, ${msg}`)
}
}
const tom = new Person('tom', 18)
console.log(tom.name) // tom
console.log(tom.age) // throw Error
抽象类
TypeScript 中,通过在 class 声明前加上 abstract 关键字来声明抽象类。抽象类只能被子类继承,而不能通过 new 关键字实例化
abstract class Animal {
eat (food: string): void {}
abstract run (distance: number): void
}
泛型
在定义函数的时候,不去指定类型,在调用时在进行类型指定
function createArray<T> (length: number, value: T): T[] {
const arr = Array<T>(length).fill(value)
return arr
}
const res = createArray<string> (3, 'string')
Flow
Flow.js 是 JavaScript 的一款数据类型检查器,它会依据变量注解的数据类型对变量进行类型校验。
安装
yarn add flow-bin --dev
初始化
flow init
使用
flow fileName
原始类型注解
const a: string = ''
const b: number = 100 // NaN // Infinity
const c: boolean = false // true
const d: null = null
const e: void = undefined
const f: symbol = Symbol()
数组类型注解
const arr1: Array<number> = [1, 2, 3]
const arr2: number[] = [1, 2, 3]
// 元组
const foo: [string, number] = ['foo', 100]
对象类型注解
const obj1: { foo: string, bar: number } = { foo: 'string', bar: 100 }
const obj2: { foo?: string, bar: number } = { bar: 100 }
const obj3: { [string]: string } = {}
obj3.key1 = 'value1'
obj3.key2 = 'value2'
函数类型注解
function foo (callback: (string, number) => void) {
callback('string', 100)
}
foo(function (str, n) {
// str ===> string
// n ===> number
})
特殊类型
- 直接规定数据的可用值
- 直接规定数据的多个可用类型
const a: 'foo' = 'foo'
const type: 'success' | 'warning' | 'danger' = 'warning'
type StringOrNumber = string | number
const b: StringOrNumber = 'string' // 100
const gender: ?number = undefined
// ===>
const gender: number | null | undefined = undefined
任意类型
// mixed 可视为所有类型的联合类型,为强类型,需要做好参数类型判断
function passMixed (value: mixed) {
if(typeof value === 'string') {}
if(typeof value === 'number') {}
}
passMixed('string')
passMixed(100)
// any,弱类型,不需要做类型判断(仅编写阶段)
function passMixed (value: any) {}
*存在问题
存在类型注解的编码并不能直接运行,需要通过编译去除掉类型注解
- 解决方案一:flow-remove-types
// 安装
npm i flow-remove-types --dev
// package.json
"scripts": {
"build": "flow-remove-types src -d dist/", // 指定导出路径
"prepublish": "yarn run build"
}
// 使用
npm run build
- 解决方案二:babel preset
// 安装
yarn add @babel/core @babel/cli @babel/preset-flow --dev
// 添加配置文件 .babelrc
{
"presets": [
"@babel/preset-flow"
]
}
// package.json
"scripts": {
"build": "babel src -d dist/", // 指定导出路径
"prepublish": "yarn run build"
}
// 使用
npm run build