Typescript类型系统FLOW静态检查基本规范

目录
  • 类型系统
    • 强类型和弱类型(类型安全)
    • 静态类型与动态类型(类型检查)
  • JavaScript自由类型系统的问题
  • Flow静态类型检查方案
  • Typescript语言规范与基本应用
    • Typescript作用域
    • Typescript原始类型
    • Typescript Object类型
    • Typescript数组类型
    • Typescript元组类型(turple)
    • Typescript枚举类型(enum)
    • TypeScript函数类型
    • TypeScript任意类型
    • 隐式类型判断
    • TypeScript类型断言
    • TypeScript接口(Interface)
    • TypeScript类(class)
    • TypeScript抽象类
    • TypeScript泛型
    • TypeScript类型声明

Typescript是一门基于JavaScript之上的语言,重点解决了JavaScript自由类型系统的问题。

使用Typescript可以大大提高代码的可靠程度。

类型系统

强类型和弱类型(类型安全)

强类型:语言层面限制函数的实参类型必须与形参类型相同

弱类型:语言层面不会限制实参的类型

由于这种强弱类型之分根本不是某一个权威机构的定义,所以导致后人对这种鉴定方式的细节,出现了不一致的理解。但整体上大家的鉴定方式都是在描述强类型有更强的类型约束,而弱类型中几乎没有什么约束。

强类型语言中不允许有任意的隐式类型转换,而弱类型语言中则允许任意的数据隐式类型转换。

强类型不允许随意的隐式类型转换,而弱类型则是允许的。

变量类型允许随时改变的特点,不是强弱类型的差异。

静态类型与动态类型(类型检查)

  • 静态类型:一个变量声明时它的类型就是明确的,而且声明过后,它的类型就不允许再修改。
  • 动态类型:运行阶段才能够明确变量类型。动态类型语言中的变量没有类型,变量中存放的值是有类型的。

JavaScript就是动态型语言,而且变量的类型随时可以改变。

常用编程语言:

JavaScript自由类型系统的问题

JavaScript是弱类型且动态类型,甚至可以说它没有类型。它的特征就是[任性]、[不靠谱],缺失了类型系统的可靠性。

JavaScript没有编译环节

大规模应用下,弱类型/动态类型这种优势就变成了短板。

弱类型的问题:君子约定有隐患,强制要求有保障。

强类型的优势:

  • 错误更早暴露
  • 代码更智能,编码更准确
  • 重构更牢靠
  • 减少不必要的类型判断

Flow静态类型检查方案

  • Flow是JavaScript的静态类型检查器。
  • 弥补了JavaScript的不足,为JavaScript提供了更完善的类型系统。
  • 工作原理就是通过在代码当中添加一些类型注解方式来去标记代码中变量或参数应该是什么类型的。
//@flow
function sum(a: number, b: number) {
    return a + b
}
console.log(sum(10, 20));
console.log(sum('10', '20'));

Flow只是一个小工具。

安装:flow-bin

通过编译除注解

  • 1.安装flow-remove-types依赖
  • 2.使用JavaScript编译工具babel配合flw插件

flow开发者工具:flow language support

类型注解

function add(a:number,b:number){
	return a+b
}
let num:number = 90
function foo():void{}

flow原始类型

const a: string = 'foobar'
const b: number = Infinity // NaN // 100
const c: boolean = false // true
const d: null = null
const e: void = undefined
const f: symbol = Symbol()

flow数组类型

const arr1: Array<number> = [1, 2, 3]
const arr2: number[] = [1, 2, 3]
// 元组
const foo: [string, number] = ['foo', 100]

flow对象类型

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'

flow函数类型

 //@flow
function foo (callback: (string, number) => void) {
  callback('string', 100)
}
foo(function (str, n) {
  // str => string
  // n => number
})

flow特殊类型

// 字面量类型
const a: 'foo' = 'foo'
const type: 'success' | 'warning' | 'danger' = 'success'
// ------------------------
// 声明类型
type StringOrNumber = string | number
const b: StringOrNumber = 'string' // 100
// ------------------------
// Maybe 类型
const gender: ?number = undefined

任意类型 Mixedany

//@flow
// string | number | boolean | ....
function passMixed (value: mixed) {
  if (typeof value === 'string') {
    value.substr(1)
  }
  if (typeof value === 'number') {
    value * value
  }
}
passMixed('string')
passMixed(100)
// ---------------------------------
function passAny (value: any) {
  value.substr(1)
  value * value
}
passAny('string')
passAny(100)

Typescript语言规范与基本应用

任何一种JavaScript运行环境都支持。功能更为强大,生态也更健全、更完善。

Typescript是JavaScript的超集。

微软自研的开发工具对Typescript支持特别好。

Typescript(渐进式)–前端领域中的第二语言。

Typescript缺点:

  • 语言本身多了很多概念
  • 项目初期,Typescript会增加一些成本

使用Typescript之前要先安装依赖。

标准库就是内置对象所对应的声明。

显示中文错误信息:yarn tsc --locale zh-CN,vs-code也可以设置locale为中文

Typescript作用域

我们可以用立即执行函数/export导出模块来创建一个单独作用域。

//立即执行函数
(function () {
    const a = 9
})()
//模块导出
export aa = {
    a: 23
}

Typescript原始类型

//原始数据类型
const a: string = 'foo'
const b: number = 100  //NaN/Infinity
const c: boolean = true  //false
const d: boolean = null
const e: void = undefined
const f: null = null
const g: undefined = undefined
const h: symbol = Symbol()

Typescript Object类型

并不单指普通的对象类型,而是泛指所有的非原始类型:对象、数组、函数。

//Object类型
const aa: object = function () { }  //[]//{}
const obj: { foo: number, bar: string } = { foo: 123, bar: 'aaa' }

更专业的方式是使用接口。

Typescript数组类型

有两种定义方式:

  • 使用Array泛型
  • 使用元素类型+[]
//数组类型
const arr: Array<number> = [1, 2, 3]
const arr1: number[] = [1, 2, 3]

Typescript元组类型(turple)

是一种特殊的数据结构,其实元组就是一个明确元素数量以及每个元素类型的数组,各个元素的类型不必要完全相同。定义方式:字面量方式

//元组类型
//元组(tuple)
export { }  //确保跟其他示例没有成员冲突
const tuple: [number, string] = [10, 'rock']
console.log(tuple[0]);  //10
console.log(tuple[1]);  //rock
//解构赋值
const [num, age] = tuple
Object.entries({
    foo: 123,
    zar: 432
})

Typescript枚举类型(enum)

enum Status {
    Draft = 'aaa',
    Unpulished = 'bbb',
    Published = 'ccc'
}

如果确认代码中不会使用索引器去访问枚举,就可以使用常量枚举。

//常量枚举
const post = {
    title: 'Hello',
    content: 'TypeScript',
    status: 'ok'
}

枚举类型会入侵到我们运行时的代码,它会影响到我们编译后的结果。我们在TypeScript中使用的大多数类型,它在经过编译转换后,最终都会被移除掉,因为它只是为了我们在编译过程中做类型检查,但枚举类型不会,它最终会变为一个双向键值对对象。

TypeScript函数类型

JavaScript中又两种函数定义方式:

函数声明

//函数声明方式
// function func1(a: number, b?: number): string {
// function func1(a: number, b: number=90): string {
function func1(a: number, ...rest: number[]): string {
    return 'hello'
}
func1(12, 34)
func1(30)

使用参数可选、参数默认值、剩余参数都需要放在参数列表的最后一个参数位置。

函数表达式

//函数表达式
const func2 = (a: number, b: number) => string = function (a: number, b: number): string {
    return 'func2'
}

TypeScript任意类型

因为any是弱类型,也是动态类型,所以TypeScript不会对any做类型检查。所以它存在类型安全问题,我们不要轻易去使用它。

function stringify(value: any) {
    return JSON.stringify(value)
}
stringify('string')
stringify(123)
stringify(true)
let foo: any = 'string'
foo = 100
foo.bar()

隐式类型判断

如果我们没有通过类型注解去标注一个变量,TypeScript会根据这个变量的使用情况去推断这个变量的类型。

//隐式类型推断
let age = 10 //number
// age = 'aaa'
let foo;
foo = 45
foo = 'aaa'

虽然定义变量时如果不给它指定类型,也不给初始值,TypeScript会自动帮他注解为any类型,但还是建议定义时就注明类型。

TypeScript类型断言

在某些特殊情况下,TypeScript无法去推断一个变量的类型,而我们作为开发者,我们根据代码的使用情况,我们是会明确知道这个变量到底是什么类型的。类型断言的方式:

  • 使用as关键字
  • 在变量前面使用<>(JSX中不能使用)
const nums = [12, 34, 56]
const res = nums.find(i => i > 10)
//断言方式一--as关键字
const num1 = res as number
//断言方式二---泛型
const num2 = <number>res

类型断言并不是类型转换,类型转换是代码在运行时的概念,而类型断言是代码在编译时的概念。当代码编译过后,断言也就不存在了。

TypeScript接口(Interface)

一种规范或者一种契约。它可以用来去约定对象的结构。去使用一个接口,就必须去遵守它所有的约定。

interface Post {
    title: string
    content: string
}
function printPost(post: Post) {
    console.log(post.title);
    console.log(post.content);
}
printPost({
    title: 'hello',
    content: 'welcome'
})
//hello
//welcome

TypeScript中的接口只是为了我们有结构的数据,去做类型约束的,在实际运行阶段,它并没有任何意义。

  • 可选成员
  • 只读成员
  • 动态成员
interface Post {
    title: string
    subtitle?: string   //可选成员
    content: string
    readonly summary: string  //只读成员
}

TypeScript类(class)

类的特征:描述一类具体事物的抽象特征。

类可以用来描述一类具体对象的抽象成员。

ES6以前,JavaScript都是通过函数+原型模拟实现类。ES6开始,JavaScript中有了专门的class。

TypeScript增强了class的相关语法。

class Person {
    name: string
    age: number
    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
    sayHi(msg: string): void {
        console.log((`I am ${this.name}, ${msg}`));
    }
}

类的访问修饰符(默认是public修饰符)

class Person {
  public name: string // = 'init name'
  private age: number
  protected gender: boolean
  constructor (name: string, age: number) {
    this.name = name
    this.age = age
    this.gender = true
  }
  sayHi (msg: string): void {
    console.log(`I am ${this.name}, ${msg}`)
    console.log(this.age)
  }
}
class Student extends Person {
  private constructor (name: string, age: number) {
    super(name, age)
    console.log(this.gender)
  }
  static create (name: string, age: number) {
    return new Student(name, age)
  }
}

const tom = new Person('tom', 18)
console.log(tom.name)
// console.log(tom.age)
// console.log(tom.gender)
const jack = Student.create('jack', 18)

类的只读属性readonly

protected readonly gender:boolean

类与接口

接口就是把共同的特征封装起来。

interface EatAndRun {
    eat(food: string): void
    run(distance: number): void
}
class Person implements EatAndRun {
    eat(food: string): void {
        console.log(`美美的吃:${food}`);
    }
    run(distance: number) {
        console.log(`直立行走:${distance}`);
    }
}
class Animal implements EatAndRun {
    eat(food: string): void {
        console.log(`美美的吃:${food}`);
    }
    run(distance: number) {
        console.log(`直立行走:${distance}`);
    }
}

一个接口只约束一个能力,一个类型去实现多个接口。

interface Eat {
    eat(food: string): void
}
interface Run {
    run(distance: number): void
}
class Person implements Eat, Run {
    eat(food: string): void {
        console.log(`美美的吃:${food}`);
    }
    run(distance: number) {
        console.log(`直立行走:${distance}`);
    }
}
class Animal implements Eat, Run {
    eat(food: string): void {
        console.log(`美美的吃:${food}`);
    }
    run(distance: number) {
        console.log(`直立行走:${distance}`);
    }
}

TypeScript抽象类

抽象类与接口有点类似,也可以用来去约束子类中必须拥有某个成员。

但是抽象类可以包含一些具体的实现,但是接口只是成员的抽象,不包含具体的实现。

抽象类不能用new去实例了,只能去继承。

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 d = new Dog()
d.eat('肉')
d.run(200)

TypeScript泛型

泛型:我们在定义函数、接口或类时,没有指定具体的类型,等到使用时再去指定具体类型的特征。

function CreateNumberArray(length: number, value: number): number[] {
    const arr = Array<number>(length).fill(value)
    return arr
}
function CreateStringArray(length: number, value: string): string[] {
    const arr = Array<string>(length).fill(value)
    return arr
}
function CreateArray<T>(length: number, value: T): T[] {
    const arr = Array<T>(length).fill(value)
    return arr
}
const res = CreateArray<string>(3, 'foo')

TypeScript类型声明

一个成员在定义时没有声明类型,在使用时单独为它做出明确声明。

import { camelCase } from 'lodash'
import qs from 'query-string'
qs.parse('?key=value&key2=value2')
declare function camelCase(input: string): string
const res = camelCase('hello')

以上就是Typescript类型系统FLOW静态检查基本规范的详细内容,更多关于Typescript类型FLOW静态检查的资料请关注我们其它相关文章!

(0)

相关推荐

  • TypeScript中枚举类型的理解与应用场景

    目录 一.是什么 二.使用 数字枚举 字符串枚举 异构枚举 本质 三.应用场景 总结 一.是什么 枚举是一个被命名的整型常数的集合,用于声明一组命名的常数,当一个变量有几种可能的取值时,可以将它定义为枚举类型 通俗来说,枚举就是一个对象的所有可能取值的集合 在日常生活中也很常见,例如表示星期的SUNDAY.MONDAY.TUESDAY.WEDNESDAY.THURSDAY.FRIDAY.SATURDAY就可以看成是一个枚举 枚举的说明与结构和联合相似,其形式为: enum 枚举名{     标识

  • 详解 TypeScript 枚举类型

    目录 1. 数字枚举 2. 字符串枚举 3. 反向映射 4. 异构枚举 5. 常量枚举 6. 枚举成员类型和联合枚举类型 (1)枚举成员类型 (2)联合枚举类型 7. 枚举合并 前言: TypeScript 在 ES 原有类型基础上加入枚举类型,使得在 TypeScript 中也可以给一组数值赋予名字,这样对开发者比较友好,可以理解枚举就是一个字典. 枚举类型使用enum来定义: enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, F

  • 一文了解TypeScript数据类型

    目录 基础类型 any类型 数组 元组 Interface 函数 类型自推 联合类型(二选一甚至多选一) class 枚举 基础类型 ts中支持更多的类型 let age: number = 10 // Number let firstName: string = '凉宸' // String let lastName: string = '凉宸' // String let isMary: boolean = true // boolean let unde: undefined = unde

  • TypeScript枚举类型

    目录 1.概述 2.数字枚举 2.1反向映射 3.字符串枚举 4.const枚举 5.总结 1.概述 所谓的枚举类型就是为一组数值赋予名字. enum类型在C++.Java语言中比较常见,TypeScript在JavaScript原有的类型基础上也增加了enum类型. 比如我们需要定义一组角色,需要使用数字表示,就可以使用如下代码定位: enum role{ STUDENT, TEACHER, ADMIN } 上面代码中我们定义了role为一个枚举类型,这个里面有是三个值,TypeScript会

  • TypeScript基础类型介绍

    目录 1.基础类型 2.对象类型 2.1数组 2.2元组 2.3对象 3.类型推断 3.1类型联合中的类型推断 3.2上下文类型 4.类型断言 TS 的静态类型可以人为的分为两类: 基础类型:像布尔值(boolean).数字(number).字符串(string).Any(任意类型).Void(无类型).Null. Undefined.Never(无值类型) 对象类型:像数组.函数.对象.枚举.元组. 1.基础类型 TS的类型定义主要通过以下示例代码中演示的方式进行定义: ;(function

  • Typescript类型系统FLOW静态检查基本规范

    目录 类型系统 强类型和弱类型(类型安全) 静态类型与动态类型(类型检查) JavaScript自由类型系统的问题 Flow静态类型检查方案 Typescript语言规范与基本应用 Typescript作用域 Typescript原始类型 Typescript Object类型 Typescript数组类型 Typescript元组类型(turple) Typescript枚举类型(enum) TypeScript函数类型 TypeScript任意类型 隐式类型判断 TypeScript类型断言

  • TypeScript 运行时类型检查补充工具

    TypeScript是静态类型系统,在编译时做类型检查.一般而言,如果项目所用到的所有库.模块都是基于ts的,那么静态类型已经可以避免大部分编程层面的类型问题.不过,在一些场景下来,单纯静态类型是无法解决问题的,部分数据是动态传入到系统中的,主要包含场景如下: 第三方数据源(接口API.本地持久化存储.postMessage等) 第三方调用者传参 全局状态变更 当然,还有其他可能,总之,单纯靠静态类型检查,无法解决运行时类型问题.因此,我写了tyshemo这个工具.它可以帮助我们完成运行时的类型

  • TypeScript类型系统自定义数据类型教程示例

    目录 TypeScript 类型系统和自定义数据类型 什么是类型系统 函数类型 类型别名 可选参数 默认参数 函数重载 接口类型 可选属性 只读属性 接口扩展 多重接口声明 接口的索引签名 用接口描述函数 类类型 implements关键字 类的静态端类型和实例端类型 将 this 作为类型 将 this 作为参数 枚举 枚举类型 枚举的成员类型 枚举的成员 字面量类型 联合类型 交叉类型 泛型 泛型函数 泛型接口 泛型类 在工厂函数中使用泛型 泛型约束 在泛型约束中使用类型参数 在泛型中使用条

  • vue项目配置使用flow类型检查的步骤

    你是否经常在debug那些简单可避免的bug?可能你给函数传参的时候搞错了参数的顺序,或者本来应该传个Number类型的参数,你传了一个String类型?JavaScript的弱类型是这一类bug的罪魁祸首,静态类型语言中不存在此类bug.Flow就是JavaScript的静态类型检查工具,该库的目标在于检查JavaScript中的类型错误,开发者通常不需要修改代码即可使用,故使用成本很低.同时,它也提供额外语法支持,使得开发者能更大程度地发挥Flow的作用. 一.flow的安装 flow可以直

  • golang一些常用的静态检查工具详解

    一.背景 俗话说,工欲善其事,必先利其器.go 作为一个对基础功能封装非常好的语言,对编码体验,如何更高效地写出高性能代码,都是考虑非常好的.因此,如何能够写出更美观.更安全的golang代码,也是我们需要关注的目标.go 本身也提供了非常多的工具供我们使用. 这里先将所有常用的指令放到这个表格中: 二.gofmt 主要修复代码格式,比如代码块的tab. 2.1 参数说明 -l: 仅打印需要替换的文件名字,不替换文件内容 如下: -r: 指定替换规则,格式:-s "pattern -> r

  • 使用mypy对python程序进行静态检查

    目录 前言 1.安装 2.执行 3.常用的内置类型 4.配置文件 最后的话 前言 在此之前,我认为 Python 的类型提示就是一个花瓶,看起来好看,但并没有实质的作用,因为即使类型写错了,或者传错了,程序仍然可以运行,直到我发现了 mypy 这个工具.今天就来聊一聊 mypy. mypy 是 Python 中的静态类型检查器.写完带有类型提示的代码之后,先别运行行,用 mypy 命令来检查下你的代码,如果有错误,会提示你,这让 Python 的类型提示有了真正的作用.后续开发的过程中可以强制

  • Go语言自定义linter静态检查工具

    目录 前言 Go语言中的静态检查是如何实现? 制定linter规则 方式一:标准库实现custom linter 方式二:go/analysis 集成到golang-cli 前言 通常我们在业务项目中会借助使用静态代码检查工具来保证代码质量,通过静态代码检查工具我们可以提前发现一些问题,比如变量未定义.类型不匹配.变量作用域问题.数组下标越界.内存泄露等问题,工具会按照自己的规则进行问题的严重等级划分,给出不同的标识和提示,静态代码检查助我们尽早的发现问题,Go语言中常用的静态代码检查工具有go

  • 详解js静态检查工具eslint配置文件

    ESLint 是一个 Javascript 静态检查工具,它可以帮你养成良好的编程习惯 { // 环境定义了预定义的全局变量. "env": { //环境定义了预定义的全局变量.更多在官网查看 "browser": true, "node": true, "commonjs": true, "amd": true, "es6": true, "mocha": true

  • pycharm 对代码做静态检查操作

    对于下面这种情况,java c这些提前编译的语言,不给你运行机会就立马报错了,但对于动态语言运行之后才能报错,用运行的方法来检查代码错误是在是太坑了,这是py对比静态语言的巨大劣势,尤其是代码文件多行数较大时候,劣势有些明显. #coding=utf8 import time class A(object): def __init__(self): self.name = 'xiaomin' def fun(): for i in range(100): time.sleep(10) print

  • Flow之一个新的Javascript静态类型检查器

    今天我们兴奋的发布了 Flow 的尝鲜版,一个新的Javascript静态类型检查器.Flow为Javascript添加了静态类型检查,以提高开发效率和代码质量.更明确的说,静态类型检查提供的好处像早期错误检查,帮助你发现一些只有在运行时才能发现的错误,以及代码智能感知,它会帮助代码维护,查找,重构和优化. 我们设计Flow的所有功能构建在现有Javascript规范之上.因为Flow主动地在后台工作,所以额外的编译开销很小.Flow并不要求开发者如何编写代码 -- 她用一套复杂的算法分析你熟悉

随机推荐