Skip to content

TypeScript基础

1064字约4分钟

TypeScript

2024-08-13

接口

在接口中进行函数声明有以下的两种方式

interface User {
  name: string
  age: number
  // 第一种声明函数方式
  sayHello: () => void
  // 第二种es声明函数的方式
  sayHi(): void
}

对应的实现对象

const user: User = {
  name: "John",
  age: 30,
  sayHello() {
    console.log(this.name)
  },
}

user.sayHello()

定义函数类型的接口

/**
 * 函数参数类型接口
 */
interface Dog {
  (age: number): boolean
}

使用类型别名可以这样写

/**
 * 使用类型别名定义函数类型
 */
type Dog = {
  (age: number): boolean
}

具体实现的方法

function createDog(dog: Dog) {
  if (dog(1)) {
    console.log("This is a dog")
  }
}

接口继承

interface User {
  name: string
}

interface VipUser extends User {
  name: number
}

已有的属性将不能被覆盖,上面将会报错。(注意,这种情况只是出现在两种相同属性不同类型时)

使用类型别名的方式则可以进行覆盖

type User = {
  name: string
}

type VipUser = {
  name: number
} & User

const u: VipUser = {
  name: "1",
}

枚举

使用枚举可以写出更优雅的代码,当我们需要对值进行修改时,可以直接修改,而无需手动修改。

/**
 * 枚举类型不赋值的话默认是number类型,从0开始。
 */
enum Sex {
  Male,
  Female,
}

使用字符串类型的枚举值

enum Sex {
  male = "",
  female = "",
}

可以使用对象的 Object.values获取枚举中所有的值

Object.values(Sex).forEach((item) => {
  console.log(item)
})

函数重载

/**
 * 函数的重载
 * @param a
 * @param b
 */
function sum(a: number, b: number): number
function sum(a: string, b: string): string

/**
 * 具体实现
 * @param a
 * @param b
 * @returns
 */
function sum(a: number | string, b: number | string): number | string {
  if (typeof a === "number" && typeof b === "number") {
    return a * b
  } else if (typeof a === "string" && typeof b === "string") {
    return a + b
  }
  return 0
}

通过重载,我们可以进行以下调用方法

sum(1, 2)
sum("1", "2")

class User {
  readonly id: number // 不能改变
  // public name: string
  age: number
  gender: "" | "" = ""
  pid?: string

  // 私有属性
  private publishNumber: number = 3 // 每天一共可以发布多少文章
  private currentNumber: number = 0 // 当前可以发布的文章数量

  constructor(public name: string, age: number) {
    this.id = Math.random()
    // this.name = name
    this.age = age
  }

  publish(title: string) {
    if (this.currentNumber < this.publishNumber) {
      console.log("发布一篇文章:", title)
      this.currentNumber++
    } else {
      console.log("你今日发布的文章数量已达到上限")
    }
  }

  /**
   * 私有方法
   * @returns
   */
  private getPublishNumber(): number {
    return this.publishNumber
  }
}

具体使用

const u = new User("aa", 2)

console.log(u.name)

u.gender = ""

u.publish("文章1")
u.publish("文章2")
u.publish("文章3")
u.publish("文章4")
u.publish("文章5")

泛型

约束在类身上,泛型可以约束在方法、参数、类

class ArrayHelper<T> {
  shuffle(arr: T[]): T[] {
    for (let i = 0; i < arr.length; i++) {
      const randomIndex = this.getRandomNumber(0, arr.length)
      const temp = arr[i]
      arr[i] = arr[randomIndex]
      arr[randomIndex] = temp
    }
    return arr
  }

  private getRandomNumber(min: number, max: number): number {
    return Math.floor(Math.random() * (max - min)) + min
  }
}

泛型也可以继承哦,这样就可以有了约束

interface HasNameProperty {
  name: string
}

/**
 * 泛型约束
 */
function getName<T extends HasNameProperty>(o: T): string {
  return o.name
}

多泛型

function mixinArray<T, K>(arr1: T[], arr2: K[]): (T | K)[] {
  if (arr1.length !== arr2.length) {
    throw new Error("数组长度不一致")
  }
  const result: (T | K)[] = []
  for (let i = 0; i < arr1.length; i++) {
    result.push(arr1[i])
    result.push(arr2[i])
  }
  return result
}

具体使用

const arr1 = [1, 2, 3]
const arr2 = ["1", "2", "3"]

console.log(mixinArray(arr1, arr2))

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2016", // 编译后目标代码版本
    "module": "CommonJS", // 设置编译结果中使用的模块化标准
    "lib": ["ES6"], // 运行环境
    "outDir": "./dist", // 编译输出目录
    "strictNullChecks": true, // 可以获得更严格的空类型检查,从此以后null、undefined只能赋值给自身
    "moduleResolution": "Node", // 设置解析模块的模式
    "noImplicitUseStrict": false, // 编译结果中不使用"use strict"
    "removeComments": true, // 编译结果中删除注释
    "noEmitOnError": true, // 错误时不生成错误结果
    "esModuleInterop": true, // 启用es模块化交互非es模块导出
    "strictPropertyInitialization": true // 更加严格的属性初始化检查
  },
  "include": ["./src"] // 需要编译的文件
}

字典

export type CallBack<T, U> = (key: T, val: U) => void

export class Dictionary<K, V> {
  private keys: K[] = []
  private vals: V[] = []

  /**
   * 访问器属性
   */
  get size() {
    return this.keys.length
  }

  /* set size(val: number) {

  } */

  set(key: K, val: V) {
    const index = this.keys.indexOf(key)
    if (index === -1) {
      this.keys.push(key)
      this.vals.push(val)
    } else {
      this.vals[index] = val
    }
  }

  get(key: K): V | undefined {
    const index = this.keys.indexOf(key)
    if (index !== -1) {
      return this.vals[index]
    }
    return undefined
  }

  forEach(callback: CallBack<K, V>) {
    this.keys.forEach((k, i) => {
      const v = this.vals[i]
      callback(k, v)
    })
  }

  has(key: K) {
    return this.keys.includes(key)
  }

  delete(key: K) {
    const index = this.keys.indexOf(key)
    if (index !== -1) {
      this.keys.splice(index, 1)
      this.vals.splice(index, 1)
      return true
    }
    return false
  }
}