枚举
//首字母大写
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 的好处
- ts是js的加强版,给js添加了可选的静态类型或者基于类的面向对象变成,ts的功能bijs只多不少
- ts是面向对象变成的语言,包含了类、接口的概念
- ts在开发时候就能给出编译错误,js的错误只能在运行时候体现
- 作为强类型的语言,可明确知道所有数据的类型
使用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(':');
});