美文网首页
前端系统学习 4. TS

前端系统学习 4. TS

作者: stanf1l | 来源:发表于2022-01-16 15:53 被阅读0次

基础知识

基础类型: number string boolean array object undefined void

1. enum 枚举的使用

2. type 和 interface 区别

3. 联合类型 | 类似的概念

如果 type D = A | B | C

  1. D 必须含有 A B C 中一个的所有成员
  2. D 的其他成员必须是 A B C 中的成员

type A = {
  a: number,
  b: number,
  c: number
}
type B = {
  a: number,
  d: number,
  e: number
}
type C = {
  a: number,
  f: number,
  g: number
}
type D = A | B | C

const sth: D = {
  a: 1,
  b: 1,
  c: 1,
  d: 1,
  g: 1,
  // h: 1
}

4. 交叉类型 & 类似的概念

5. typeof 可以基于已有的变量/函数获得他的类型

function toArray(x: number): Array<number> {
  return [x]
}

type Func = typeof toArray

6. keyof 获取一个对象当中的 key

interface Person {
  name: number,
  age: number
}

type XX = keyof Person // 'name' | 'age'

const x: XX = 'age'

7. in 遍历枚举类型

type Keys = "a" | "b" | 'c'

type Obj = {
  [key in Keys]: number
}

const obj: Obj = {
  a: 1,
  b: 1, 
  c: 1,
  // d: 1
}

8. extends

泛型:对于类型的参数

interface A<T> {
  a: T
}

const b: A<number> = {
  a: 1
}

extends 用来约束泛型的类型

interface ILengthwise {
  length: number
}

function log<T extends ILengthwise> (arg: T): T {
  return arg
}

log({length: 1, width: 1})

9. Partial

将类型成员都变为可选

interface XX {
  name: string,
  sex: string
}

type AA = Partial<XX>
/**
 * {
 *  name?: string,
 *  sex?: string
 * }
 */

10. Required

将类型成员都变为必选

面试题及实战

  1. 你觉得 ts 的好处是什么?

1.1 TypeScript是 JavaScript 的加强版,它给 JavaScript 添加了可选的静态类型和基于类的面向对象编程,它拓展了 JavaScript 的语法。
1.2 TypeScript 是纯面向对象的编程语言,包含类和接口的概念。
1.3 TS 在开发时就能给出编译错误,而 JS 错误则需要在运行时才能暴露
1.4 作为强类型的语言,可以明确知道数据的类型。代码可读性极强,方便多人协作。
1.5 TS 中有很多方便的特性,如可选链。

  1. type 和 interface 的区别

重点:type 用来描述类型,interface 用来描述接口

2.1 都可以描述一个对象或函数

interface User {
  name: string
  age: string
}

interface SetUser {
  (name: string, sex: string): void
}

type User {
  name: string,
  age: string
}

type SetUser = (name: string, age: string) => void

2.2 都允许拓展

interface 和 type 都可以拓展,而且两者可以相互拓展。效果差不多,但是两者语法不同

// interface extends interface
interface Name {
  name: string
}
interface User extends Name {
  age: number
}

// type extends type
type Name = {
  name: string
}
type User = Name & { age: number }

// interface extends type
type Name = {
  name: string
}
interface User extends Name {
  age: number
}

// type extends interface
interface Name {
  name: string
}
type User = Name & {
  age: number
}

2.3 只有 type 能做的

type 可以声明基本类型别名,联合类型,元组等类型

// 基本类型别名
type Name = string

// 联合类型
interface Dog {
  wong()
}
interface Cat {
  miao()
}
type Pet = Dog | Cat

// 具体定义数组每个位置的类型
type PetList = [Dog, Cat]

// 获取一个 js 变量的类型时,使用 typeof
const div = document.createElement('div')
type D = typeof div
  1. 如何基于一个已有的类型,扩展出一个大部分内容相似,但是有部分区别的类型?

首先可以通过 Pick 和 Omit

interface User {
  name: string,
  sex: string,
  age: number
}

type BB = Pick<User, 'name' | 'age'>

其次可以通过 Partial、Required

再者可以通过泛型。

  1. 写一个 routerHelper
import { Dictionary } from 'vue-router/types/router';
import Router, { RoutePath } from '../router'

type BaseRouteParam = Dictionary<string>

export interface IndexParam extends BaseRouteParam {
  index: string
}

export interface AboutParam extends BaseRouteParam {
  about: string
}

export interface UserParam extends BaseRouteParam {
  user: string
}

export interface ParamMap {
  [RoutePath.Index]: IndexParam,
  [RoutePath.About]: AboutParam,
  [RoutePath.User]: UserParam,
} 

class RouterHelper {
  static push<T extends RoutePath> (path: T, query: ParamMap[T]) {
    return Router.push({
      path, query
    })
  }
}

export default RouterHelper
  1. 写一个 CountDown
import { EventEmitter } from 'eventemitter3'

enum CountDownStatus {
  running,
  stoped
}

export enum CountDownEventName {
  START = 'start',
  RUNNING = 'running',
  STOP = 'stop'
}

type CountDownEventMap = {
  [CountDownEventName.START]: [],
  [CountDownEventName.STOP]: [],
  [CountDownEventName.RUNNING]: [RemainTimeData, number],
}

interface RemainTimeData {
  hours: number,
  minutes: number,
  seconds: number,
  counts: number
}

export default class CountDown extends EventEmitter<CountDownEventMap> {
  private static COUNT_TICKS = 10
  private static SECOND_TICKS = 100 * CountDown.COUNT_TICKS
  private static MINITE_TICKS = 60 * CountDown.SECOND_TICKS
  private static HOUR_TICKS = 60 * CountDown.MINITE_TICKS

  private status: CountDownStatus = CountDownStatus.stoped
  private remainTime = 0
  private endTime = 0
  private step = 100
  private timer = 0

  constructor(endTime: number, step: number) {
    super()

    this.endTime = endTime
    this.step = step

    this.start()
  }

  public start() {
    if (this.status === CountDownStatus.stoped) {
      this.status = CountDownStatus.running
      this.emit(CountDownEventName.START)
      this.countdown()
    }
  }

  public stop() {
    if (this.status === CountDownStatus.running) {
      this.status = CountDownStatus.stoped
      this.emit(CountDownEventName.STOP)
      clearTimeout(this.timer)
    }
  }

  private countdown() {
    this.emit(CountDownEventName.RUNNING, this.parseRemainTime(), this.remainTime)
    this.timer = requestAnimationFrame(() => {
      this.remainTime = Math.max(this.endTime - Date.now(), 0)
      if (this.remainTime > 0) {
        this.countdown()
      } else {
        this.stop()
      }
    });
  }

  private parseRemainTime() {
    let time = this.remainTime

    const hours = Math.floor(time / CountDown.HOUR_TICKS)
    time = time % CountDown.HOUR_TICKS
    const minutes = Math.floor(time / CountDown.MINITE_TICKS)
    time = time % CountDown.MINITE_TICKS
    const seconds = Math.floor(time / CountDown.SECOND_TICKS)
    time = time % CountDown.SECOND_TICKS
    const counts = Math.round(time / CountDown.COUNT_TICKS)

    return {
      hours, minutes, seconds, counts
    }
  }


}
  1. tsc 原理

源码 => 扫描器(Scanner)=> Token 流 => 解析器(Parser) => AST =>

  1. 类型检查
  2. 生成 js 代码

相关文章

网友评论

      本文标题:前端系统学习 4. TS

      本文链接:https://www.haomeiwen.com/subject/buvfhrtx.html