关于Javscript 中变量类型
第一章: 简介
什么是TypeScript: Based on javascript , + 类型系统 + es6+ => Javascipt(编译结果)
特点: 类似 Flow , 渐进式,学习成本, 新概念引入
语言类型:
- 弱态:(类型安全)
- 强态:(类型安全)- 在语言层面,函数 实参 与形参 类型完全相同 - 不允许任意类型转换
- 静态:(类型检查)- 声明时,变量类型就明确, 且不能更改
- 动态:(类型检查)- 运行阶段, 才能明确类型,可更改
Javascript :
- 弱 + 动
- 脚本语言 - 不需要编译,直接在运行环境中运行
- 类型体统薄弱 - 基本无类型限制, 缺乏类型可靠性。
强弱对比:
弱问题:
//example 1 : 未定义先用, 发现问题要等到运行时
const obj = {}
setTimeout(()=>{
obj.foo()
},10000)
// example 2 // 计算?拼接 == 功能变了
var sum = (a, b) => a + b
console.log(sum(1,2)) //3
console.log(sum(1,'100')) //'1100'
// example 3: 对象属性名会自动转化为string
const obj ={}
obj[true] = 100
console.log(obj['true']) // 100
强优势:
- 早发现早治疗
- 更智能更准确(开发工具推断数据类型)
- 重构(在未来改变变量名等)
- 减少类型判断
第二章: Flow
JavaScript's 静态类型检查器(2014 Facebook 提出)
基本要点就是 - 类型注解: 变量名 :变量类型 (a:number)
快速上手:
1. Flow 是一个npm 模块, 需要初始化 package.json文件: npm init (+ 一顿enter) / yarn init --yes
2. 安装 flow 模块: npm install flow-bin --dev / yarn add flow-bin --dev
3. 初始化flowconfig 文件: flow-init
4. 执行/ 终止: yarn flow / yarn stop
npm init 创建 package.json 不要慌: https://heynode.com/tutorial/create-packagejson-file/, 一通 enter 就行, 具体看这个
⚠️ 注意事项 :
1. // @flow
2. 关闭: JavaScript › Validate
返回结果:
编译解除:
此时 js 代码无法正常运行: 应为 :变量注解 不是 js 语法, 因此node 执行js 文件报错
node getting_started.js
Guohais-MacBook-Pro:flow guohaiqu$ node getting_started.js
/Users/guohaiqu/Desktop/flow/getting_started.js:2
function sum (a:number, b:number ) { // javascript
^
SyntaxError: Unexpected token ':'
at Object.compileFunction (node:vm:355:18)
at wrapSafe (node:internal/modules/cjs/loader:1038:15)
at Module._compile (node:internal/modules/cjs/loader:1072:27)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10)
at Module.load (node:internal/modules/cjs/loader:988:32)
at Function.Module._load (node:internal/modules/cjs/loader:828:14)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12)
at node:internal/main/run_main_module:17:47
解除注解:(flow官方方法)
安装 移除注解模块: yarn add flow-remove-types --dev
触发: yarn flow-remove-types . -d dist (yarn flow-remove-types 文件源 -d 文件存放地)
解除注解:( babel)
yarn add @babel/core @babel/cli @babel/preset-flow --dev
.babelrc
{
"presets": ["@babel/preset-flow"]
}
yarn babel . -d dist
插件: Flow Language Support , 自动提示插件, 保存后显示
//@flow
// 原始数据类型
const a: string = 'foo'
const b: number = 100
const c: boolean = true
const d: null = null
const e: void = undefined
const f: symbol = Symbol()
//============================================================
// 数组类型限制 2种限制方法
const arr_1: Array<number> = [1,2,3]
const arr_2: number[] = [1,2,3]
// 元组: 固定长度的数组, 函数返回值时常用
const foo: [string, number] = ['foo', 123]
//============================================================
//对象类型🚫 2种限制方法
const obj: {foo: string, bar: number} = {foo: 'foo', bar:123}
//可选成员: name?
const obj_optional: {foo?: string, bar: number} = {bar:123}
//空置
const obj_empty: {[string]:string} = {}
//整活
const obj_empty: {[string]:string} = {'class': 'front-end', 'school':'lagou'}
obj_empty.name = 'guohai'
obj_empty.lastnanme = 'qu'
// objNmae:{[string]: string} 意味着可以存放任意数量,但 key value 数据类型被限制
//============================================================
//函数类型🚫。: 参数 + 返回值 限制🚫
function foo(callback:(string, number) => void) {
callback('i have', 100)
}
function callback(a, b) {
console.log(a , b )
}
foo(callback)
// 字面量:
a: 'foo': 'foo' // a 中只能存放 ‘foo’
const type: 'success' | 'warning' = 'warning'
// or
type String_or_Number = string | number
let xg: String_or_Number = 'gg'
xg = 10
// maybe 类型: 值可以存放 x + null + undefined
let gender: ?number = 0 // | null | undefined
gender = null
gender = undefined
语法步骤 以免出错:
1. 先写 普通 js 即: const obj = {foo: 'foo', bar:123}2. 后写 obj 注视: obj: { foo: string, bar: number}
// maybe 类型 ❓在类型前 gender: ?number
//对象的 optional key,❓在key后面 : {foo?: string, bar: number}//整活: const test:{age? : ?number, name: string } = {name: "guohai"}
const test:{age? : ?number, name: string } = {name: "guohai"}
const test1:{age? : ?number, name: string } = {age: null, name: "guohai"}
console.log(test, test1) //{ name: 'guohai' } { age: null, name: 'guohai' }
Mixed + Any 全部类型
强: valueMixed: mixed
弱: valueAny: any
第三章: TypeScript
类型限制基本与flow一致
快速上手:
npm模块(意味着 初始化 package.json, yarn init --yes), 全局/本地 安装(yarn add typescript --dev)
编译ts文件tsc(typescript complier): yarn tsc filename.ts
初始化ts配置文件:yarn tsc --init
配置文件:
“target” : “es5” ---- 将 ts 转化为 es5
“moudle”:“commonjs”, moudle 配置
“sourceMap”: true : 开启源代码映射(会生成一个文件)
“outDir”:“dist” : js输出目录
“rootDir”:“src” :ts输出目录
“strict”:“true” : 开启严格模式
"lib": [ "ES2015" , "DOM"] : 标准库声明
preference >typescript local >zh-cn 中文报错在vscode 中
Object 类型
除原始类型外的全部类型, {}, [], function(){}
隐式类型推断
let age = 18. //推断为 number 不可更改
age = "guohai". // ts error
类型断言(当js无法判断,明确告诉js 是什么类型)
const nums = [1,2,3]
const res = nums[1]
//method1: recommend
const num1 = res as number
//method2:
const num2 = <number>res
元组
// 固定长度和类型
const tuple : [number, string] = [18, 'guohai']
const age = tuple[0]
const name = tuple[1]
const [age, name] = tuple
枚举
enum enum_example {
draft = 0 // 是=
unpublished = 1
published = 2
}
const enum enum_example1 { //常量枚举 // 建议
draft
unpublished
published
}
const post = {
title: "hello"
status: enum_example1.draft // 0 //enum_example.draft
}
函数
function foo(a?:number, b:number=1, ...rest: number[]):string {
return 'gg'
}
foo(1,2)
const foo1:(a: number, b:number)=>string = function (a:number, b?:number):string {
return 'gg'
}
接口 interface
约束object 的结构,
约定成员数量,
成员类型 content: string
成员可选subtitle?:string,
成员属性 readonly summary: string
interface Post { // 一个接口
title: string
content: string
}
function printPost(post: Post){ // 使用接口类型约束形参
console.log(post.title)
console.log(post.content)
}
printPost({ // 调用 //传入符合接口的数据
title: "hello",
content:"js"
})
//动态 接口
interface Cache {
[key: string] : string
}
const cache : Cache = {}
cache.foo = 'value1'
类
private : 类内访问
protected: 子类可访问
public: 可省略
static: 静态方法
readonly: 只读 / 在访问修饰符后面 protected readonly gender :boolean = 0
age: number // 成员需要先声明 才能在 constructor里用
class Person {
name: string // 不可缺
age: number // 不可缺, 需要先声明
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
const jack = new Person("jack", 18)
class Person {
name: string // 不可缺
age: number // 不可缺, 需要先声明
private constructor(name: string, age: number) {
this.name = name
this.age = age
}
static create (name: string, age: number) {
this.name = name
this.age = age
}
}
const jack = Person.create("jack", 18)
类与接口 class Person implements Eat { eat(food:string):void {....} }
interface Eat{
eat(food:string):void //约束 eat function 参数和返回值
}
class Person implements Eat {
eat(food:string):void {
console.log(food)
}
}
抽象类
// 抽象类 === 只能被继承不能被实例化
abstract class Animal {
eat (food: string):void {
console.log( food )
}
abstract run(distance:number):void // 抽象方法 //无具体实现
}
class Dog extends Animal {
run(distance:number): void {
console.log(distance)
}
}
const newd = new Dog()
newd.eat("ddd")
泛型: <T>, 把定义是不能明确的类型变成参数,在使用时传递类型参数
//T
function createArray<T>(length:number, value:T):T[] {
const array = Array<T>(length).fill(value)
console.log(array)
return array
}
createArray<string>(3,'gg')