TypeScript

时间:2021-2-20 作者:admin

概述

  • 解决JavaScript类型系统的问题
  • 大大提高代码可靠程度

强类型与弱类型

  • 类型安全

  • 强类型:

    • 语言层面限制函数的实参类型必须与形参类型相同
    • 有更强的类型约束
    • 不允许任意的隐式类型转换

    弱类型:

    • 语言层面不限制实参类型
    • 几乎没有约束
    • 允许任意的隐式类型转换(理解)

JavaScript不是强类型!不然编译过程就报错了

python是强类型

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

静态类型与动态类型

  • 类型检查

  • 静态类型:变量声明时它的类型就是明确的,声明后类型就不允许再修改

    动态类型:

    • 运行阶段才能够明确变量类型,也可以随时变化(区别)
    • 变量是没有类型的,存放的值是有类型的

JavaScript自有类型系统的问题

  • 弱类型 / 动态类型
  • JavaScript没有编译环节

JavaScript的短板

弱类型的问题

  • 必须等到运行阶段才能发现一些编译异常。异步

  • 类型不明确,函数功能有可能发生改变

  • 对象索引器错误的用法

    需要每个人约定规则

强类型优势

  1. 错误更早暴露
  2. 代码更智能、编码准确
  3. 重构更牢靠
  4. 减少不必要的类型判断

Flow静态类型检查方案

Flow:JavaScript的类型检查器。标记类型注解

上手

yarn add flow-bin --dev
添加//@flow
yarn flow init
yarn flow stop
yarn flow 

编译移除注解

flow只在编码阶段去找问题,结束之后可以自动移除类型注解

yarn flow-remove-types src -d dist

使用babel也可以移除

yarn add @babel/core @babel/cli @babel/preset-flow --dev
//.babel
{
    "presets":["@babel/preset-flow"]
}
yarn babel src -d dist

工具开发插件

类型推断

类型注解

let a :number = 100

原始类型

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

数组类型

const arr1: Array<number> = [1,3,4]

const arr2: number[] = [2,3,4]

//元组:固定长度的数组,一个函数返回多个返回值的时候使用
const foo: [string, number] = ['foo', 100]

对象类型

const obj1: {foo?: string, bar: number} = {
    foo: 'string',
    bar: 100
}
//?可有可无

函数类型

函数中的参数和返回值都可以设置类型注解

function foo(callback : string, number => void) {
    callback('string', 100)
}

foo(function (str, n){

})

特殊类型

  1. 字面量类型

    const a: 'foo' = 'foo'
    
    const type: 'success' | 'warning' | 'danger' = 'success'
    
  2. 声明类型

    type StringOrNumber = string | number
    
    const b: StringOrNumber = 'string' // 100
    
  3. Maybe类型

    const gender: ?number = undefined
    //有可能,可以是null或undefined或number
    

Mix和Any

// string | number | boolean | ....
function passMixed (value: mixed) {
  if (typeof value === 'string') {
    value.substr(1)
  }

  if (typeof value === 'number') {
    value * value
  }
}

passMixed('string')

passMixed(100)

any兼容老代码

运行环境API

const element: HTMLement| null = document.getElementById('app')//一定要传入字符串

TypeScript语言规范与基本应用

概述

  • JavaScript的超集(superset)/ 扩展集

  • 使用新特性,兼容性好

  • 任何一种JavaScript运行环境都支持

  • 功能更为强大,生态更健全,更完善

  • Angular/Vue.js3.0

  • 缺点:

    • 很多概念 接口 泛型 枚举 / 但是渐进式的
    • 项目初期增加成本

上手

yarn init --yes
yarn add typescript --dev//.bin/tsc帮助编译typescript代码
新建ts文件
yarn tsc .\src\01-getting-started.ts//转换为标准的ECMAScript3代码

配置文件

//自动生成配置文件
yarn tsc --init

原始类型

和flow相同

const a: string = 'foobar'

const b: number = 100 // NaN Infinity

const c: boolean = true // false

// 在非严格模式(strictNullChecks)下,
// string, number, boolean 都可以为空
// const d: string = null
// const d: number = null
// const d: boolean = null

const e: void = undefined

const f: null = null

const g: undefined = undefined

// Symbol 是 ES2015 标准中定义的成员,
// 使用它的前提是必须确保有对应的 ES2015 标准库引用
// 也就是 tsconfig.json 中的 lib 选项必须包含 ES2015
const h: symbol = Symbol()

标准库声明

  • 标准库就是内置对象所对应的声明
//tsconfig.json
"lib": ["ES2015", "DOM", "ES2017"]
//lib去指定所引用的标准库

中文错误消息

yarn tsc --locale zh-CN

作用域问题

  • 默认文件中的成员会作为全局成员

  • 多个文件中有相同成员就会出现冲突

  • 解决:

    1. 立即执行函数 / IIFE 提供独立作用域

      (function () {
        const a = 123
      })()
      
    2. 在当前文件使用 export,也就是把当前文件变成一个模块,模块有单独的作用域

      export {}
      //一个语法,变成局部成员
      

Object类型

  • Object并不单指普通的对象

    const foo: object = function () {} // [] // {}
    
    const obj: { foo: number, bar: string } = { foo: 123, bar: 'string' }
    //字面量类型,数量要完全一致,不能多也不能少
    

数组类型

const arr1: Array<number> = [1,2,3]
const arr2: number[] = [1,2,3]

function sum (...args: number[]){
    //prev上一次计算结果,current本次循环当前值
    reuturn args.reduce((prev, current) => prev + current, 0)
}

sum(1,2,3)

元组类型

  • 明确元素数量和元素类型的数组
const tuple: [number, string] = [18, 'zce']
const [age, name] = tuple

//获取每一个键值数组
const entries: [string, number][] = Object.entries({
  foo: 123,
  bar: 456
})

枚举类型

  • 模拟实现枚举
enum P {
    a = 0,
    b = 1,
    c = 2
}

enum P {
    a,
    b,
    c
}//默认从0开始累加,但字符串无法自动累加,需要手动去定义每个枚举变量

status:P.a
  • 会入侵到运行时的代码,影响编译后的结果,枚举最后会被编译成一个双向键值对的对象,以便使用所引器去使用枚举
    • 使用常量枚举const

函数类型

  • 形参和实参必须相同
  • 可选参数 / ?
  • 参数默认值 / 可有可无 / 必须出现在最后
  • 任意个数的参数 …rest

任意类型

Any Type

  • typescript不会对any类型进行类型检查

隐式类型推断

  • 无赋值,默认any

最好还是自己给每个变量添加类型

类型断言

  • 对于一个一定会返回某类型的函数 / 变量,就可以断言

    const num = res as number
    const num = <number>res//jsx下不能使用
    
  • 不是类型转换,是在编译过程的概念

接口

  • 约定一个对象中有具体有什么成员和什么类型

  • 约束对象的结构,使用对象去实现一个接口,就必须拥有接口中约定的所有成员

    interface Post {
        name : string
        content: string
    }
    
  • 可选成员,标记类型是undefined

    {
        name?:string
    }
    
  • 只读成员,设定后不能再修改

    {
        readonly name:string
    }
    
  • 动态成员,适用动态成员对象,如缓存对象

    interface Cache {
        [key: string]: string
    }
    const  cache: Cache = {}
    cache.foo = 'name1'
    cache.bar = '2'
    //动态添加成员,都必须是string类型的键值
    

  • 描述一类具体事物的抽象特征
  • 用来描述一类具体对象的抽象成员
  • ES6开始
  • 在类里初始化成员一定要赋值

访问修饰符

可访问级别

public //默认
private
protected//子类可以访问

只读属性

readonly只读属性,初始化后就不能再被修改

类与接口

implement类实现接口

抽象类

abstract不包含具体的实现,大类使用抽象类

  • 只能被子类继承,不能被new创造实例对象
  • 抽象方法,不需要方法

泛型

  • 复用代码,解决冗余

  • 不明确类型变成一个参数

    function createArray<T> (length: number, value: T): T[] {
      const arr = Array<T>(length).fill(value)
      return arr
    }
    
    // const res = createNumberArray(3, 100)
    // res => [100, 100, 100]
    
    const res = createArray<string>(3, 'foo')
    

类型声明


本文首发于我的GitHub博客,其它博客同步更新。

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。