Typescript相关学习

强类型和弱类型

  • 从类型安全的纬度区分 分为强和弱, 最开始是在函数参数中加类型限制, 基础理解: 强类型 不允许隐式类型转换 弱类型允许

静态类型和动态类型

  • 从类型检查的纬度,分为静态类型和动态类型, 是否允许变量申明后去修改变量值的类型

javascript是一个弱类型、 动态类型的语言,是一个任性的语言,失去了类型的约束是一个不靠谱的语言。

  • javascript是一个没有编译环节的是一个脚本语言

弱类型的一些问题

  • 必须要等到运行时才能发现语法异常
  • 类型不明确会造成函数功能发生异常
  • 隐式转换规则不清晰

强类型的一些优势

  • 错误可以提前暴露
  • 代码更智能、编码更准确
  • 重构会更牢靠
  • 减少代码层面不必要的类型判断

Flow


Flow javascript静态类型检查器

  • 通过类型注解来做类型检查

flow的基础使用

  • flow-bin 是flow的安装包,使用npm安装
  • 在需要flow检查的文件顶部加 @flow的注释,用来标识该文件需要flow来检查静态类型
  • 在文件代码中加入类型注解
  • 使用 yarn flow命令进行检查

在编译阶段移除类型注解

  • 安装 flow-remove-types
  • 执行命令 yarn flow-remove-types ./src -d dist 编译src目录下的代码,删除类型注解 到dist目录
  • babel中也有babel-flow插件可以删除类型注解

vscode中可以安装 flow-language-support 可以在编码阶段给出代码错误提示

flow的类型推断

function square(n) {
    return n * n
}
square('100') //这个时候flow就会提示类型错误,因为字符串是不能进行*运算的

类型注解(尽量添加类型注解、少交给类型推断)

const no: number = 1

function foo(): string { return '' }

function foo(): void { }

flow支持的原始数据类型

  • string number(NaN、 Infinity都是属于number类型) null undefind(需要使用void表示) Object Array Symbol

数组类型

const arr: Array<number> = [1,2,3,4,5] //需要是用泛型定义数组中每一项的类型

const arr: number[] = [1,2,3,4,5]

const arr:[string , number] = ['foo', 1] //元祖, 一般函数返回多个不同类型的值的时候使用

对象类型

const obj: {foo?: string, bar: number} = {foo: 'string', bar: 100} //?表示可选

const obj: {[string]: string} = {} //允许添加多个字符串键,和value是string的值

函数类型

  • 函数主要限制参数类型 和返回值类型类型
  • 函数作为参数传递
    function foo( callback: (string, number) => void) { callback()}

特殊情况

const type: 'success' | 'warning' | 'danger' = 'danger'

type stringOrNumber = string | number = 123

const type1:stringOrNumber = 123

const type2:?number = null // 在number类型上扩展了 null和undefined

mixed和any类型,可表示任意类型

  • 区别 mixed还是强类型(不能直接使用字符串方法或数字方法) any还是一个弱类型(可以调用任意类型的方法)

内置API的检查

const app: HTMLelement | null = document.getElementById('app')

TypeScript


TypeScript是javascript的超集,比JavaScript多了一个类型检查系统和对es新特性的完全支持,最终会被编译成js应用,可以兼容到es3

TypeScript可以说是前端领域的第二语言,现阶段react、angular、vue3 都使用了。
缺点:

  • 本身多了很多概念(接口、泛型、枚举等等)
  • 对于小项目,typescript会增加很多类型申明的成本

ts基本使用

  • 安装typescript模块
  • 模块提供了tsc命令, tsc命令会编译ts文件到js(移除类型注解、编译最新的语法)

tsconfig

  • yarn tsc --init
  • 修改配置文件选项后,可直接执行yarn tsc进行ts的语法编译

ts基本类型

  • ts基本类型的使用和flow是一样的,需要注意的是标准库申明文件的使用(例如symbol是es2015申明文件里面申明的,而console是浏览器对象BOM里面提供的, DOM和BOM的申明文件都在DOM里面)

错误提示可以主动设置

  • 编译时加上 --local zh-CN
  • 编译器vscode中,在设置中搜索typescript的,可以语言就可以了

不同文件中命名冲突

  • 文件使用const等申明后是在全局作用下,那么在下一个文件中使用相同命名就会提示冲突,解决方案:
  • 1.加上立即执行函数,把作用域编程函数作用域
  • 2.添加 export {} 将当前文件编程一个模块,变成一个局部作用域

Object类型

  • object不单指{}, 也可以是数组和函数
  • 使用字面量写法的时候,需要值和申明需要完全一致,不能多也不能少。
    const obj:{foo: string} = {foo: '1234', more: 123} // 这个时候more:123就会报错

数组类型和flow使用一致

const arr: Array<number> = [1,2,3,4,5] //需要是用泛型定义数组中每一项的类型

const arr: number[] = [1,2,3,4,5]

元祖类型

  • 可以理解为固定长度、固定元素类型的数组

枚举类型

  • 某个值固定只能使用某几个值

  • 枚举类型会入侵我们代码,简单来说,就是会改变我们编译后代码

  • 加了const就会变成常量枚举

      const enum statusProp  {
          start = 0,
          ing = 1,
          end = 2
      }
    
      const status: 0|1|2 = 1
      const status2 = statusProp.start
    

函数的类型约束

function fn (a: number, b: number) :string {
    return 'abc'
} //参数的形参和实参必须保持一致
fn(1,3)
// fn(1,3,2) // 2就会报错

任意类型--typescript不会是any类型的数据做类型检查

function stringify(value: any) {
    return JSON.stringify(value) //stringify可以接收任何类型的参数
}

隐式类型推断

  • 如果我没有写类型注解,typescript会根据我们写的代码来推断数据的类型

let age = 18; age = 'string' //这个时候就会报错,ts推断age为number类型

类型断言

有时候typescript无法推断出一个变量的类型,作为开发人员我们可以主动的判断出是什么类型。那么我们就告诉typescript这个变量的类型

const arr = [1,2,3,5,6]
const res = arr.find((e) => e>0)
const res1 = res as number
const res2 = <number>res //在jsx环境下会和标签产生冲突
const num = 100 - res1

接口(可以理解为一个规范或者约定)interface 规范一个对象所拥有的属性

interface Content {
    title: string
    message: string
    desc?: string
    readonly btn: string
}

function printContent(content: Content) {
    console.log(content.title)
    console.log(content.message)
}
printContent({
    title: "haha",
    message: "this is"
})
// 动态类型
interface Cache {
    [key: string]: string
}
const cache: Cache = {}
cache.foo = "1234"

类(描述一类具体事物的抽象特征)以及类的修饰符

class Person {
    name: string
    private age: number //私有属性
    protected gender: boolean //对子元素public
    constructor(name: string, age: number) {
        this.name = name
        this.age = age
        this.gender = true
    }
    say (msg: string) :void {
        console.log(`my name is ${this.name}`)
    }
}

const ton = new Person('ton', 18)
ton.name
ton.age //私有属性无法访问

class Student extends Person {
    constructor(name: string, age: number) {
        super(name, age)
        console.log(this.gender)
    }
}

类与接口

接口约定了类必须实现的方法

interface EatAndRun {
    eat(food: string): void
    run(distance: number): void
}
interface Eat {
    eat(food: string): void
    run(distance: number): void
}
interface Run {
    run(distance: number): void
}
class Person1 implements EatAndRun {
    eat(food: string) {
        console.log(`慢慢的吃${food}`)
    }
    run(distance: number) {
        console.log(`双脚跑步${distance}`)
    }
}
class Animals implements Eat, Run {
    eat(food: string) {
        console.log(`呼噜呼噜的吃${food}`)
    }
    run(distance: number) {
        console.log(`四脚跑步${distance}`)
    }
}

抽象类 (可以约束类的成员,与接口不同的是,可以包含一些成员的实现)一般大的类,我们会使用抽象类

abstract class Animal { //使用类抽象类之后,该类不能使用new来实例化
    eat(food: string) {
        console.log(`呼噜呼噜的吃${food}`)
    }
    abstract run(distance: number): void //抽象方法
}

class Dog extends Animal {
    run(distance: number): void {
        console.log(`4脚爬行${distance}`)
    }
    
}
const dog = new Dog()
dog.eat('gutou')
dog.run(100)

泛型

我们在定义函数、接口、类的时候我们没有定义类型,在调用的时候传入类型

function creatNumArray(len: number, value: number): number[] {
    return Array<number>(len).fill(value)
}

function creatStrArray(len: number, value: string): string[] {
    return Array<string>(len).fill(value)
}

function creatArray<T>(len: number, value: T): T[] {
    return Array<T>(len).fill(value)
}

const arrs = creatArray<string>(10, '2')
const arrn = creatArray<number>(10, 1)

类型声明 declare

引入第三方模块的时候,函数或者类没有对参数进行限制,我们需要手动添加声明,或者安装对应的声明模块

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容