TypeScript的那些事

随着前端技术的更新迭代,TS已经算是很耳熟目染了,也能发现很多技术栈都用到了TS来进行开发,以下主要是针对刚开始初学TS需要掌握的内容

强类型与弱类型

强类型:
不允许有随意的隐式类型转化,例如传入的参数数据格式必须保持一致,否则会直接报语法错误
(优势,会在语法阶段直接爆出错误,代码更加智能,编码准确,重构定位问题,减少一步数据类型判断)
弱类型:
允许有隐式类型转换发生,如果传入参数不一致的情况,不会发生语法错误
(存在的问题:错误不能在语法层面直接报错,会发生类型转换,使得函数方法改变,数据类型不一致)

静态类型和动态类型

静态类型:
规定刚开始赋变量值后,不能对数据类型进行修改
动态类型:
赋值后是可以对变量的类型进行修改的
在这里插入图片描述

Javascript自身类型系统的问题

类同于弱类型和动态类型的问题

Flow静态类型检查

可以通过引入flow来对我们代码类型进行报错检测
步骤:

  1. 在项目代码中安装flow-bin用来检测我们代码的数据类型是否一致
  2. 使用过程中需要通过@flow来引入
  3. 特殊格式是无法通过vscode的自主语法校验的,需要关掉语法
//@flow
function sum (a:Number, b:Number) {
    return a+b
}
// sum(100, 100)
sum('100', '100') -----开启flow检测会会直接报数据类型不一致的错误

Flow的使用更多是在代码书写阶段进行数据类型校验的,那么在编译阶段就需要将添加的flow移除掉,此处有两种方法可以工具化帮助我们移除

  1. 使用flow自带的工具flow-remove-types进行转化
  2. 使用babel工具,yarn add @babel/core @babel/cli @babel/proset-flow来进行文件的转化

Flow的原始类型

const a: string = 'football'
const b: number = 123
const c:boolean = true
const d: null = null
const e: void = undefined

-------数组类型
const arr1: Array<number> = [1,2,3]
const arr2: number[] = [1,2,3]
-------对象类型
const obj1: {foo:string,bar:number} = {foo:'string',bar:123}
const obj2: {foo?:string,bar:number} = {bar:123}
-------函数类型
function foo() :number }{
    return 100
//如果什么都不返回,就需要定义成void类型
}
-------maybe类型
const type: 'success'|'waring'|'allright' = 'success'
const b: StringOrNumber = 'string'
const gender: ?number = undefined
-------任意类型
function passMixed(value:mixed){} //保留强类型特性
function passAny(value:any){} //依旧是弱类型可以调用方法
---同样如果在使用dom元素获取的时候,都有api声明的一些数据类型限制
Typescript语言规范与基本应用

Object类型:不单单指的是传统{},还包括函数,数据,对象

const Object = function(){} //[] //{}
const Object:{foo:number,bar:string} = {foo:123,bar:'string'}

Array类型:

const arr: Array<Number> = [1,2,3]
const arr: number[] = [1,2,3]
//来限制传入的参数为数组结构的参数
function sum (...args:number[]) {
  return args.reduce((pre,current) => pre+current,0)
}

元组类型:固定长度来返回内容

const tuple: [number,string] = [18,'string']
const [age,name] = tuple
Object.entries({
  foo:123-----键值数组就是用元组表示的
})
//其中包括react中使用的usestatue就是元组返回结果

枚举类型:

enum PostStatus {
//如若不赋值,直接从1开始数字累加,也可以是字符串默认值,不过需要每一个都定义
  Draft = 1,
  Unpublished = 2,
  Published = 3
}
//最后转化会出现双线数据定义,可以通过const变量来移除
const post = {
  status: PostStatus.Draft
}

函数类型:

...rest来接受任意参数的接收值
function func(a:number,b:number=10,...rest:number[]):string {
  return 'string'
}
func(10,20)

任意类型:

function stringify(value:any){
  return JSON.stringify(value)
}
//any可以用来接收任意类型参数,一般不用存在安全性,但是如果兼容老代码可以使用

类型断言:类型转化是在执行过程发生,但是类型断言只存在于编译过程

const res = nums.find(i => i>0)
const num1 = res as number
const num2 = <number>res //JSX下不能使用,会被当作标签
接口

是Typescript中用来约束对象结构的,在编译之后并没有接口相关的代码,没有实际意义

export {}
interface Post {
    title: String
    content: String
    subtitle ?: String   ---用来表示可有可无
    readonly summary: String ---用来标识只读成员
}
function printPost (post) {
    console.log(post.title)
    console.log(post.content)
}

printPost({
    title:'Hello worlds' ,
    content: 'A javascript superset'
})

//定义不确定性键值对成员
interface Cache {
  [prop: String]: String
}
const cache: Cache = []
cache.foo = 'value'
TypeScript类的基本使用

不同于JS的类使用,TS类中变量定义之后需要对其进行提前声明

export {}
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}`)
  }
}
类的修饰符

一般有三种修饰

class Person {
  public name: String  ---公共成员对象
  private age:Number   ---私有成员对象,外部不能够进行访问,只能在对象内部访问
  protected gender: boolean
  ---保护对象,只允许在此类中访问定义的成员
}
class Student extends Person {
  private cosntructor (name: String, age:Number){
    super(name,age)
    console.log(this.gender)  ---是可以进行访问的
  }
  static create (name: string,age:number){
    return new Student(name,age)
  }
}
//私有继承类之后,外部无法正常调用new来构造
const Jack = Student.creat('jack', 18)
类和接口

可以帮助我们定义不同类之间相同的公共属性

export {}
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):void {
        console.log(`直立行走 ${distance}}`, )
    }
}
class Animal implements Eat, Run {
    eat(food:String):void {
        console.log(`动物咀嚼 ${food}`, )
    }
    run(distance:Number):void {
        console.log(`爬行动物 ${distance}}`, )
    }
}
抽象类的实现

如果定义了抽象类,就不可以new构造,只能通过子类来继承

export {}
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 dog = new Dog()
dog.eat('骨头')
dog.run(100)
泛型

当我们定义不确定类型参数的时候,为了避免冗余,可以通过泛型来定义不同数据类型

export{}
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')
类型声明

对于一些引入的第三方模块,可能没有对象的类型声明

  • 添加相应的types声明模块@types/lodash
  • 手动添加
declare function camelCase (input: string): string
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值