TS基础_02

107 阅读4分钟

枚举

//首字母大写
enum [枚举名称]{
    枚举成员1, 
    枚举成员2,.....
}

enum Week {
    /** 周日*/
    Sunday,
    /** 周一*/
    Monday,
    /** 周二*/
    Tuesday,
    /** 周三*/
    Wednesday,
    /** 周四*/
    Thursday,
    /** 周五*/
    Friday,
    /** 周六*/
    Saturday 
}

枚举是一种类型,可以做变量的类型注解

    let Oneweek:Week;

也可以为变量赋值

    let sund = Week.Sunday;

枚举成员只能访问不能赋值

    Week.Sunday = '周日';  //报错

枚举还支持反向映射

    Week['Sunday'] = 0
    Week[0] = Sunday

type

type与interface在使用的时候总感觉有相似的地方,但是使用还是有本质的区别的

   //都可以描述变量与函数
   interface User {
       name : string
       age:number
   }
   let person :User = {
       name:'lisi',
       age:20
   }
   type User = {
       name:string
       age:number
   }
   let Person:User = {
       name:'lisi',
       age:18
   }
   // type可以声明联合类型和元组类型
   //联合类型
   interface Cat {
       name:string
   }
   interface Camera{
       status:string
   }
   type mixin = Cat | Camera
   //元组类型:定义数组每个位置上的类型
   type arr = [Cat,Camera]
   
   //interface可以合并声明
   interface Cat {
       name :string
   }
   interface Cat {
       age:number
   }
   /**Cat {
   * name:sting
   * age:number
   *}
   */ 
   //不清楚什么时候用interface/type,能用 interface 实现,就用 interface , 如果不能就用 type 。
   
   
    interface A {
        name:string
        age:number
    }
    const geta :A ={
        name:"a",
        age:1,
    }
    // 如果我想局域A生成一个新的类型里面name和age都是可选项
    // 难道我要像下面这么做么
    // interface B {
    //     name?:string
    //     age?:number
    // }

    // 等价于

    type B =Partial<A>
    // Partial将A的类型里面的key全都变成了可选值
     let b :B = {
        name:'1'
     }
    // 相反的Required可以将所有的key变成必选项
    type C = Required<B>

当我们进行类型注解的时候我们可以使用

    interface User {
        name :string
    }
    //以下三种类型注解方式都是一样的意思
    let a = <User>{}
    let b = {} as User
    let c: User = {}

上面我们用到了联合类型 |,与之对应的还有交叉类型&

interface User {
   name:string
}
interface People{
    age:number
}
const Person = User | People
let xiaoming = <Person>{
    name:'lisi',
    sex:1 //报错
}
// 联合类型做类型注解的时候需要保障变量里面必须有一个其中的值
const animal  = User & People
// 交叉类型做类型注解的时候 需要保障两个值都有否则会报错
let xiaoming = <Person>{
    name:'lisi',//报错缺少一个age
}

in

//in 遍历枚举类型
type Keys = "a"|"b"|"c"

// key与对象的联合操作
type Obj = {
    [key in Keys]:number
}
let obj:Obj = {
    a:1,
    b:2,
    c:3
}

泛型

泛型:类型的参数(个人理解就是类似函数的传参)

let  a = new Array<string>()
interface User {
    name:string
}
const getName = <T extends User>(arg:T):T =>{
    return arg;
}
getName({name:'lisi',age:18})

extend:用来约束泛型

如何基于一个已有的类型扩展出一个大部分内容相似,但是部分区别的类型

interface Test {
    name;string
    sex :number
    htight:string
}
// 只包含sex
type Sex = Pick<Test,"sex">
// 排除sex
type WithoutSex = Omit<Test,"sex">


interface Abc {
    name:[number,string]
}

ts 的好处

  1. ts是js的加强版,给js添加了可选的静态类型或者基于类的面向对象变成,ts的功能bijs只多不少
  2. ts是面向对象变成的语言,包含了类、接口的概念
  3. ts在开发时候就能给出编译错误,js的错误只能在运行时候体现
  4. 作为强类型的语言,可明确知道所有数据的类型

使用ts完成一个时间倒计时

// EventEmitter(事件派发器)是一个对事件进行监听的对象,简单来说就是为事件写回调函数,
// 当触发一个事件执行后,会执行为该事件绑定的回调函数。
import { EventEmitter } from "eventemitter3";

export interface RemainTimerData{
    /**天数*/ 
    days:number
    hours:number
    minutes:number
    seconds:number
    count:number
} 
// 声明三种状态
enum CountedownStatus {
    running,
    paused,
    stop
}
// 要订阅的事件类型
export enum CountdownEventName{
    START = 'start',
    STOP = 'stop',
    RUNNING= 'running'
}
// 定义订阅事件的名称及参数
interface CountdownEventMap{
    [CountdownEventName.START]:[];
    [CountdownEventName.STOP]:[];
    [CountdownEventName.RUNNING]:[RemainTimerData,number]//回调函数的参数
}
// 格式化时间补零操作
export function fillZero(num: number) {
    return `0${num}`.slice(-2);
}

export class Countdown extends EventEmitter<CountdownEventMap>{
    // 格式化时间
    private static COUNT_IN_MILLISECOND:number = 1 * 100
    private static  SECOND_IN_MILLISECOND:number = 10 * Countdown.COUNT_IN_MILLISECOND
    private static  MINUTE_IN_MILLISECOND:number = 60 * Countdown.SECOND_IN_MILLISECOND
    private static  HOUR_IN_MILLISECOND:number = 60 * Countdown.MINUTE_IN_MILLISECOND
    private static  DAY_IN_MILLISECOND:number = 24 * Countdown.HOUR_IN_MILLISECOND




    // 私有变量
    private endTime:number
    private step:number
    private remainTime:number
    private status:CountedownStatus = CountedownStatus.stop 
    constructor(endTime:number,step:number = 1e3){
        super()
        this.endTime = endTime
        this.step= step
    }
    // 开始
    public start() {
        this.emit(CountdownEventName.START)
        this.status = CountedownStatus.running
        this.countdown()
    }
    // 停止
    public stop(){
        this.emit(CountdownEventName.STOP)
        this.status = CountedownStatus.stop;    
    }

    public countdown(){
         if(this.status !== CountedownStatus.running){
             return;
         }
         this.remainTime = Math.max(this.endTime - Date.now(),0)
         this.emit(CountdownEventName.RUNNING,this.parseReadminTime(this.remainTime),this.remainTime)
         if(this.remainTime>0){
             setTimeout(() => {
                 return this.countdown()
             }, this.step);
         }else{
             this.stop()
         }
    }
    // 时间跳动
    private parseReadminTime(remainTime:number) : RemainTimerData {
        let time= remainTime;
        const days = Math.floor(time/Countdown.DAY_IN_MILLISECOND)
        time = time % Countdown.DAY_IN_MILLISECOND

        const hours = Math.floor(time/ Countdown.HOUR_IN_MILLISECOND)
        time = time% Countdown.HOUR_IN_MILLISECOND
        
        const minutes = Math.floor(time/ Countdown.MINUTE_IN_MILLISECOND)
        time = time% Countdown.MINUTE_IN_MILLISECOND

        const seconds = Math.floor(time/ Countdown.SECOND_IN_MILLISECOND)
        time = time % Countdown.SECOND_IN_MILLISECOND
        
        const count = Math.floor(time/ Countdown.COUNT_IN_MILLISECOND)

        return {
            days,
            hours,
            minutes,
            seconds,
            count
        }
        
    }
}

//如何使用
 import { Countdown, CountdownEventName, fillZero } from '@/lib/countdown';

 const countdown = new Countdown(Date.now() + 60 * 60 * 1000, 10);
 countdown.on(CountdownEventName.RUNNING, (remainTimeData) => {
     const { hours, minutes, seconds, count} = remainTimeData;
     this.timeDisplay = [hours, minutes, seconds, count].map(fillZero).join(':');
 });