6. Typescript 类型体操

Typescript 类型体操

用发布订阅模式解耦

const eventNames = ['API:UN_AUTH', 'API:INVALID']
type EventNames = (typeof eventNames)[number]

class EventEmitter {
  private listeners: Record<string, Set<Function>> = {
    'API:UN_AUTH': new Set(),
    'API:INVALID': new Set()
  }

  on(eventName: EventNames, listener: Function) {
    this.listeners[eventName].add(listener)
  }

  emit(eventName: EventNames, ...args: any[]) {
    this.listeners[eventName].forEach((listener) => listener(...args))
  }
}

export default new EventEmitter()

前置的不定量参数(类型标注)

type JSTypeMap = {
  string: string
  number: number
  boolean: boolean
  undefined: undefined
  object: object
  symbol: symbol
  bigint: bigint
  null: null
}

type JSTypeNames = keyof JSTypeMap

type ArgsType<T extends JSTypeNames[]> = {
  [I in keyof T]: JSTypeMap[T[I]]
}

declare function addImpl<T extends JSTypeNames[]>(...args: [...T, (...args: ArgsType<T>) => any]): void

不可变类型

type DeepReadonly = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P]
}

interface Obj {
  a: number
  b: string
}
// Readonly 浅的不可变类型
let obj: Readonly<Obj> = {
  a: 1,
  b: '2'
}

使用元祖生成联合类型

const colors = ['♥', '♦', '♣', '♠'] as const
const values = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'] as const
type Color = (typeof colors)[number]
type Value = (typeof values)[number]
### TypeScript 类型体操概述 TypeScript 提供了强大的类型系统,允许开发者创建复杂的泛型和条件类型。这些功能通常被称为“类型体操”,因为它们涉及对类型的复杂操作。 #### 条件类型与 `infer` 关键字 当需要从现有类型中提取子类型时,可以使用带有 `infer` 的条件类型。这使得可以从函数返回值或其他结构化数据中抽取特定部分的类型[^4]。 ```typescript // 定义一个通用类型来解析 Promise 返回值的类型 type AsyncReturnType<T> = T extends Promise<infer U> ? U : never; async function fetchData(): Promise<{ data: string }> { return { data: "example" }; } type ResultType = AsyncReturnType<Awaited<ReturnType<typeof fetchData>>>; // 结果为 {data:string} ``` #### 映射类型与索引签名 映射类型能够基于已有接口或类型定义新的类型,并且可以通过修改某些属性来进行扩展或限制。利用 `keyof` 和索引访问类型 (`T[K]`) 可以方便地处理对象内部各个字段之间的关系[^5]。 ```typescript interface Person { name: string; age?: number; } // 创建一个新的只读版本的人类信息类型 type ReadonlyPerson = { readonly [P in keyof Person]: Person[P]; }; const person: ReadonlyPerson = { name: "Alice" }; person.name = "Bob"; // Error: Cannot assign to 'name' because it is a read-only property. ``` #### 泛型约束中的 `extends` 通过给定参数附加额外的信息,如指定其必须满足某个接口的要求,从而增强灵活性并减少错误的可能性。此方法常用于库设计当中,以便更好地支持第三方模块集成[^3]。 ```typescript function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; } const user = { id: 1, username: "john_doe" }; console.log(getProperty(user, "username")); // 输出:"john_doe" ``` #### 使用 `as const` 进行更严格的推断 虽然不建议频繁使用显式的类型转换(`as`),但在某些情况下确实有助于提高编译器的理解能力;而 `as const` 则提供了一种更加安全的方式来声明不可变的数据结构[^2]。 ```typescript const roles = ["admin", "editor"] as const; type Role = typeof roles[number]; // "admin" | "editor" let currentRole: Role = "viewer"; // Type '"viewer"' is not assignable to type '"admin" | "editor"' ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值