二、TS核心语法+各种实战应用(下)

143 阅读6分钟

1.TS函数类型个相关解构

type ParamsType = {
  name: string
  age: number
  bool: boolean
}
function info(obj: ParamsType) {
  console.log(obj.name, '===name===')
  console.log(obj.age, '===age===')
  return 4
}
const subObj: ParamsType = { name: 'zhangsan', age: 12, bool: false }
info(subObj)

函数解构

type ParamsType1 = {
  name: string
  age: number
  bool?: boolean
}
function info({ name, age }: ParamsType1) {
  console.log(name, '===name===')
  console.log(age, '===age===')
  return 4
}
info({ name: 'zhangsan', age: 12 })

2.TS函数类型复杂实战

手写 Promise 开头两段源码

3.Vue3源码,更深入理解接口和type的区别

语法差异

  • interface 使用 interface 关键字定义
  • type 使用 type 关键字定义

合并能力

  • interface 接口可以重名 type不可以重名
  • interface 同名接口会被合并为一个接口 type会产生冲突 发生报错

对象类型 vs 声明类型

  • interface 用于定义对象类型,可以描述对象的结构``属性方法 也可以实现继承(extends)
  • type 可以定义任何类型,包括基础类型,支持联合类型 '|', 交叉类型 '&' , 元祖

type定义类型

// 定义基础类型
type num = number

// 定义联合类型1.
type Lian = string | number | symbol

// 定义联合类型 2.
interface Test1 {
  id: string
}
interface Test2 {
  id: string
  numStr: string
}

type ParamsType = Test2 | Test1
const value: ParamsType = { id: '61060', numStr: '321' }

接口继承 interface

interface Test1 {
  id: string
}
interface Test2 {
  id: string
  numStr: string
}

// 继承多个接口以逗号分割
interface Test3 extends Test1, Test2 {
  name: string
  age: num
}

// 继承单个接口
interface Test4 extends Test1 {
  name: string
  age: num
}

接口合并

interface Test1 {
  id: string
}
interface Test1 {
  id: string
  numStr: string
  age: number
  name: string
}

const str: Test1 = { id: '1', name: '23214' }

4.元祖

满足以下三点的数组就是元祖

  1. 在定义时每个元素的类型都确定
  2. 元素值的数据类型必须是当前元素定义的类型
  3. 元素值的个数必须和定义时个数相同
const salary: [string, number, number, number, number] = ['雷雷', 12000, 200, 300, 400]
// 取值  与数组取值一样
console.log(salary[0]) // 下标取值


5.TS数组和数组元素怎样同时为只读?

// as const 将数组设置为只读  约束了数组中的每一项也为常数
const arr = [10, 20, 30, 40, 50, 60] as const
arr[0] = 12 // 无法为“0”赋值,因为它是只读属性

6.可变元祖和它的应用场景?

// 可变元祖  ...any[] 可以接收多个  相当于  reset
const salary: [string, number, number, ...any[]] = ['雷雷', 12000, 200, 300, 400]

// 可变元祖解构
const { name, age, address, ...reset }: [string, number, string, ...any[]] = [
  '雷雷',
  24,
  '陕西省',
  300,
  400,
]

7.可变元组tag和tag的意义?

const { 
    name, 
    age, 
    address, 
    ...reset 
}: [
   name_: string, 
   age_: number, 
   address_: string, 
   ...reset_: any[]
] = ['雷雷', 24, '陕西省', 300, 400]
name_  age_  address_  reset_  只是为了表达 对应类型的含义

8.类、静态属性、何时用静态属性?

// 类、静态属性、何时用静态属性?
// 类就是拥有相同属性和方法的一系列对象的集合.
// 展开理解: 类是一个模具,是从这该类包含的所有具体对象中抽象出来的一个概念,类定义了它所包含的全体对象的静态特征和动态特征
class People {
  name: string
  age: number
  address: string
  static count = 0
  constructor(name: string, age: number, address: string) {
    this.name = name
    this.age = age
    this.address = address
    People.count++
  }
  doEat() {}
  doStep() {}
}
const p = new People('3213', 321, '321')
console.log(People.count)

p.doEat()
p.doStep()
// 静态成员(静态属性+静态方法)

9.企业项目何时用--静态成员?

// 我们一般会封装一个一个的工具函数
function formatDate() {}
function diffDateByDay() {}
function diffDateByHour() {}
function timeConversion(resetTime: number) {}

// 工具函数一般都是可以固定死的 不像一些订单方法 客户很多 
// 所以工具一般  定义为静态方法直接调用
// class 本身就是一个构造函数
class DateUntil {
  static formatDate() {}
  static diffDateByDay() {} // 俩个日期之间的天数计算
  static diffDateByHour() {} // 俩个日期之间的小时计算
  static timeConversion(resetTime: number) {} // 天 时 分 秒
}
// 调用
DateUntil.formatDate()

10.TS常见面试题——TS单件(例)模式的两种实现和静态成员执行的时机

  • 单例模式1.
1.直接初始化实例:在这个类中,`dateUtil` 是直接被初始化为一个 `DateUntil` 的实例。这意味着在程序开始运行时,这个实例就已经被创建了。
2.私有构造函数:与第一个类一样,这个类也有一个私有的构造函数,限制了外部的实例化。
// 单例模式旨在确保一个类只有一个实例,并提供一种全局访问点来获取该实例。
class DateUntil {
  static dateUtil = new DateUntil() // 唯一的实例对象方法

  // 1. 创建一个私有的构造方法  外部不能访问
  private constructor() {
    console.log(1)
  }
  formatDate() {
    console.log(1)
  }
  diffDateByDay() {
    console.log(1)
  }

  diffDateByHour() {
    console.log(1)
  }
  timeConversion(resetTime: number) {
    console.log(1)
  }
}

const p1 = DateUntil.dateUtil
const p2 = DateUntil.dateUtil
// 因为 p1 和 p2 都引用了同一个唯一的 DateUntil 实例。
// 这就是单例模式的作用,确保类的实例在应用程序中是唯一的。
console.log(p1 === p2)

export default DateUntil.dateUtil

11.TS常见面试题——单件(例)模式的第二种实现

  • 单例模式2.
1.使用`getInstance`方法实现单例:这个类通过一个静态的`getInstance`方法来获取
    单例实例,确保只有一个 `DateUntil` 实例存在。在这个方法内部,
    只有在 `dateUtil``null` 时才会创建实例。但是在实现时
    判断条件应该是 `!this.dateUtil`,以正确地检查实例是否存在。
        
2.私有构造函数:这个类的构造函数是私有的,这意味着外部无法直接创建`DateUntil`的实例
    只能通过 `getInstance` 方法获得实例。
class DateUntil {
  static dateUtil: DateUntil
  static getInstance() {
    // 如果为空则创建实例
    if (!this.dateUtil) {
      this.dateUtil = new DateUntil()
    }
    return this.dateUtil
  }
  private constructor() {
    console.log('立即创建')
  }
  formatDate() {
    console.log('测试')
  }
  diffDateByDay() {}
  diffDateByHour() {}
  timeConversion(resetTime: number) {}
}

总的来说,两个类都试图实现单例模式的日期工具类,但第二个类通过 getInstance 方法来创建实例,而第一个类在静态成员中直接创建了实例。两者的最大区别在于实例的创建时机以及是否有延迟加载(lazy loading)的能力。

12.TS类getter setter使用和意义

Getter 和 Setter 的意义:

Getter 和 Setter 是用来访问和修改类属性的方法,它们允许你在访问或修改属性时进行逻辑操作。Getter 用于获取属性的值,而 Setter 用于设置属性的值。这些方法可以帮助你对属性进行更加精细的控制,例如验证输入、进行计算等。

  1. 属性赋值

    • 在构造函数之外,可以通过直接访问属性来赋值。例如:this.name = name。这是最常见的属性赋值方式。
  2. 构造函数来赋值

    • 构造函数是在对象创建时执行的函数,它常用于初始化对象的属性。代码在构造函数中接收nameaddress 并将其赋值给相应的属性。
  3. 类中的某个方法

    • 可以在类中定义方法来处理属性的赋值。在你的代码中,你使用 Setter 方法 age(val: number) 来设置 _age 属性的值。

class People {
  name: string
  _age!: number
  address: string
  static count = 10
  constructor(name: string, address: string) {
    this.name = name
    this.address = address
    People.count++
  }
  // 赋值
  set age(val: number) {
    if (val > 10 && val < 128) {
      this._age = val
    } else {
      throw new Error('年龄不合适')
    }
  }
  // 获取
  get age() {
    return this._age
  }
  doEat() {
    console.log(1)
  }
  doStep() {
    console.log(2)
  }
}
const p = new People('name', 'address')
p.age = 200 // 会抛出错误
  • 代码中,尝试将 age 设置为 200,但由于在Setter方法中设置了范围限制,它会抛出错误,因为不满足条件 val > 10 && val < 128。这正是 Setter 方法的用途之一:在设置属性时进行验证和逻辑操作。