Skip to content

高级

枚举

数字枚举

typescript
enum Status {
  Uploading,
  Success,
  Failed,
}

console.log('Status.Uploading', Status.Uploading) // 0
console.log('Status["Success"]', Status['Success']) // 1
console.log('Status.Failed', Status.Failed) // 2

枚举默认编码为 0,但允许手动指定,此时如果指定 Success = 0,则 Status 的三个状态分别是 0,0,1

数字枚举允许使用计算值或者常量对其中元素进行值定义, 但元素后一位必须手动指定初始值

反向映射

一个枚举,不仅可以通过字段名得到枚举值,也可以通过枚举值得到字段名,查看一个枚举的内容:

字符串枚举

字符串枚举成员必须初始化枚举值,同时不能引入计算值\

typescript
const test2 = 'test2'
enum Message {
  Success = 'Hai, Success',
  Error = 'Sorry, Error',
  Failed = Error, // 可以使用自身的成员来当做枚举值 实际输出 Sorry, Error
}

异构枚举(不推荐使用)

枚举值有字符串类型和数字类型混合的,就叫做异构枚举.

枚举成员类型和联合枚举类型

当一个枚举值满足一定条件的时候,那么它的枚举值和枚举值成员都可以当做类型来使用.

  • 没有初始值的枚举类型 enum E {A,B,C}
  • 枚举值类型为字符串字面量的类型 enum E { A='a',B='b'}
  • 枚举值为数字类型且不包含计算类型 enum E {A=1, B=5}
typescript
enum Animals {
  Dog,
  Cat,
}
interface Dog {
  type: Animals.Dog
}
const dog: Dog = {
  type: Animals.Dog, // 等价于 0
}
console.log('dog', dog) // dog { type: 0 }

const enum

枚举是在运行时真正存在的一个对象。 其中一个原因是因为这样可以从枚举值到枚举名进行反向映射

然而有时候需求却比较严格。 当访问枚举值时,为了避免生成多余的代码和间接引用,可以使用常数枚举。 常数枚举是在enum关键字前使用const修饰符。不同于常规的枚举的是它们在编译阶段会被删除

所以常数枚举不可能有计算成员

类型推论

基础

多类型联合

上下文类型

ts 推断出了 e 参数的数据类型是 MouseEvent

类型兼容性

基础

函数兼容性

  • 参数个数

  • 参数类型

  • 返回值类型

  • 可选参数和剩余参数

  • 函数重载

    typescript
    // 重载出现的条件:方法/函数名相同,参数类型不同 或者参数数量不同 或者参数顺序不同
    function add(n: number, m: number): number
    function add(n: string, m: string): string
    function add(n: number, m: string): string
    function add(n: string, m: number): string
    
    function add(n: any, m: any): any {
      return n + m
    }
    console.log(add(2, 'hello'))
    console.log(add(2, 3))

this 类型

typescript
class Counter {
  constructor(public count: number) {
    this.count = count
  }

  add(value: number) {
    this.count += value
    return this // 返回 this 可以让类支持链式调用
  }

  sub(value: number) {
    this.count -= value
    return this
  }
}
let count = new Counter(10)
console.log('count.add(5).sub(2)', count.add(5).sub(2))

索引类型

索引类型查询操作符

typescript
// 获取指定 key 的值 使用 ts 泛型对函数的参数进行约束,使第二个参数 K 必须为对象包含的 key
function getValue<T, K extends keyof T>(obj: T, names: K[]) {
  return names.map(item => obj[item])
}

const infoObj = {
  name: '猫南北',
  age: 18,
}

let result = getValue(infoObj, ['name'])
console.log('result', result) // result [ '猫南北' ]

let result2 = getValue(infoObj, ['gender']) // Error: 不能将类型"gender"分配给类型"name"|"age"

索引访问操作符

typescript
type NameType = Info['name']
function getProperty<T, K extends keyof T>(obj: T, name: K): T[K] {
  return obj[name]
}
let result3 = getProperty(infoObj, 'age')
console.log('result3', result3) // result3 18

映射类型

基础

typescript
// 也可以使用 Ts 内置类型中的 ReadOnly和Partial来快速实现
type myInfo = Readonly<Partial<Info>>

由映射类型进行推断

增加或移除特定修饰符

keyof 和映射类型在 2.9 的升级

元组和数组上的映射类型

条件类型

基础

typescript
interface Animal {
  live(): void
}
interface Dog extends Animal {
  woof(): void
}
type Example1 = Dog extends Animal ? true : false // Example1 = true
type Example2 = RegExp extends Animal ? true : false // Example2 = false

type IdLabel = number
type NameLabel = string
type NameOrId<T extends number | string> = T extends number ? IdLabel : NameLabel
function createLabel<T extends number | string>(nameOrId: T): NameOrId<T> {
  throw ''
}
let a = createLabel('猫南北') // a:string
let b = createLabel(123) // b:number

条件约束类型

typescript
type MessageOf<T> = T['Message'] // 类型“"Message"”无法用于索引类型“T”。
type MessageOf<T extends { Message: unknown }> = T['Message']

分布式条件类型

条件类型的类型推断-infer

TS 预定于条件类型