# TypeScript 进阶

# 类型别名

类型别名用来给一个类型起个新名字

type Name = string
type NameResolver = () => string
type NameOrResolver = Name | NameResolver
function getName(n: NameOrResolver): Name {
  if (typeof n === 'string') {
    return n
  } else {
    return n()
  }
}

别名可以定义泛型

# 字符串字面量类型

字符串字面量类型用来约束取值只能是某几个字符串中的一个

🤔 数字类型可以吗

type EventNames = 'click' | 'scroll' | 'mousemove'
function handleEvent(ele: Element, event: EventNames) {
  // do something
}

handleEvent(document.getElementById('hello'), 'scroll') // 没问题
handleEvent(document.getElementById('world'), 'dblclick') // 报错,event 不能为 'dblclick'

// index.ts(7,47): error TS2345: Argument of type '"dblclick"' is not assignable to parameter of type 'EventNames'.

# 元组

数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象

let tom: [string, number] = ['Tom', 25]

# 使用

import { useState } from 'react'
const [loading, setLoading] = useState<boolean>(false)
function useState<S = undefined>(): [
  S | undefined,
  Dispatch<SetStateAction<S | undefined>>
]

# 枚举

枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝等。

enum Days {
  Sun,
  Mon,
  Tue,
  Wed,
  Thu,
  Fri,
  Sat
}
// 编译后的代码
var Days
;(function(Days) {
  Days[(Days['Sun'] = 0)] = 'Sun'
  Days[(Days['Mon'] = 1)] = 'Mon'
  Days[(Days['Tue'] = 2)] = 'Tue'
  Days[(Days['Wed'] = 3)] = 'Wed'
  Days[(Days['Thu'] = 4)] = 'Thu'
  Days[(Days['Fri'] = 5)] = 'Fri'
  Days[(Days['Sat'] = 6)] = 'Sat'
})(Days || (Days = {}))

# 手动赋值

enum Days {
  Sun = 7,
  Mon = 1,
  Tue,
  Wed,
  Thu,
  Fri,
  Sat
}
//未手动赋值的枚举项会接着上一个枚举项递增 // 7123456

# 常数枚举

const enum Days {
  Sun,
  Mon,
  Tue,
  Wed,
  Thu,
  Fri,
  Sat
}

常数枚举与普通枚举的区别是,它会在编译阶段被删除

# 外部枚举

外部枚举(Ambient Enums)是使用 declare enum 定义的枚举类型 declare 定义的类型只会用于编译时的检查,编译结果中会被删

🤔 如果定义一个能够循环选项的枚举类型

# (opens new window)

# 类和接口 (opens new window)

# 泛型

  • T(Type):表示一个 TypeScript 类型
  • K(Key):表示对象中的键类型
  • V(Value):表示对象中的值类型
  • E(Element):表示元素类型

定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

# 声明合并

如果定义了两个相同名字的函数、接口或类,那么它们会合并成一个类型:

# 函数的合并 重载

# 接口合并 类的合并 接口中的属性在合并时会简单的合并到一个接 合并的属性的类型必须是唯一的

# 类型守卫

类型保护是可执行运行时检查的一种表达式,用于确保该类型在一定的范围内。换句话说,类型保护可以保证一个字符串是一个字符串,尽管它的值也可以是一个数值。类型保护与特性检测并不是完全不同,其主要思想是尝试检测属性、方法或原型,以确定如何处理值

# in

# typeof

# instanceof

# 泛型工具类型

更多 (opens new window)

  1. typeof

在 TypeScript 中,typeof 操作符可以用来获取一个变量声明或对象的类型

interface Person {
  name: string
  age: number
}

const sem: Person = { name: 'Ivan', age: 18 }
type Sem = typeof sem // -> Person
  1. keyof

keyof 操作符可以用来一个对象中的所有 key 值

interface Person {
  name: string
  age: number
}

type K1 = keyof Person // "name" | "age"
type K2 = keyof Person[] // "length" | "toString" | "pop" | "push" | "concat" | "join"
type K3 = keyof { [x: string]: Person } // string | number
  1. in

in 用来遍历枚举类型:

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

type Obj = {
  [p in Keys]: any
} // -> { a: any, b: any, c: any }
  1. infer

在条件类型语句中,可以用 infer 声明一个类型变量并且对它进行使用

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any

以上代码中 infer R 就是声明一个变量来承载传入函数签名的返回值类型,简单说就是用它取到函数返回值的类型方便之后使用。

https://juejin.cn/post/6844904170353328135

  1. extends

有时候我们定义的泛型不想过于灵活或者说想继承某些类等,可以通过 extends 关键字添加泛型约束。

interface ILengthwise {
  length: number
}

function loggingIdentity<T extends ILengthwise>(arg: T): T {
  console.log(arg.length)
  return arg
}
  1. Partial

Partial<T> 的作用就是将某个类型里的属性全部变为可选项 ?。

/**
 * node_modules/typescript/lib/lib.es5.d.ts
 * Make all properties in T optional
 */
type Partial<T> = {
  [P in keyof T]?: T[P]
}
上次更新: 12/19/2021, 5:46:36 PM