TypeScript 05:交叉类型、索引签名、元组与 enum

TypeScript 05:交叉类型、索引签名、元组与 enum

有 JS 基础即可阅读。建议先读第 01~04 课。

1. 交叉类型 &:把多个类型「合体」

A & B 表示「同时满足 A 和 B」------和联合类型 |(满足其一)正好相反:

ts 复制代码
interface Loggable {
  log: () => string
}
interface Timestamped {
  createdAt: number
}

type Entry = Loggable & Timestamped // 且:两个都得有

const e: Entry = {
  log: () => '日志',
  createdAt: 1728800000000,
}

最常用场景:给已有类型追加字段,不用改原类型:

ts 复制代码
interface Person {
  name: string
}

type Admin = Person & { level: number } // Person 的全部 + 新增 level

const admin: Admin = { name: 'Tom', level: 3 }

同名属性类型冲突时,结果是 never(谁也满足不了):{ a: string } & { a: number } 的 a 就是 never。

2. 索引签名:给「键不固定」的对象立规矩

键是动态的(字典类数据)时,没法逐字段列,用索引签名声明「任意键 → 固定值类型」:

ts 复制代码
const scores: { [name: string]: number } = { math: 90, english: 85 }

两个要点:

  • strict 下读取结果带 undefined(键是动态的,TS 不敢保证存在):
ts 复制代码
const math = scores['math'] // number | undefined
math.toFixed(0) // ❌ Object is possibly 'undefined',先判断再用
  • 声明后所有字段必须兼容它 :{ [key: string]: string; version: number } 不合法------version 是 number,违反了「任意键都是 string」

Record<string, number> 是它的泛型等价写法。使用建议:能用具体字段就别用索引签名,它是检查强度最低的对象类型。

3. 元组 tuple:定长、定序的数组

数组 number[] 只约束「每个元素是 number」,不约束长度和位置;元组全部约束:

ts 复制代码
const point: [number, number] = [3, 4] // 恰好两个,都是 number
const bad: [number, number] = [1, '2'] // ❌ 位置类型也要对上

标签元组:给位置起名,可读性大增------多返回值的标准答案:

ts 复制代码
function divide(
  numerator: number,
  denominator: number,
): [quotient: number, remainder: number] {
  return [Math.floor(numerator / denominator), numerator % denominator]
}

const [quotient, remainder] = divide(17, 5)

剩余元素:[name: string, ...points: number[]] = 第一个是名字,后面随便几个数字。

4. enum 与它的现代替代品

enum 是 TS 的私有语法------它会生成一个真实的运行时对象,而不是可剥掉的注解:

ts 复制代码
enum Status {
  Loading = 'loading',
  Success = 'success',
}
console.log(Status.Success) // 'success'------运行时真有这个对象

这正是它的问题:第 01 课说过「TS = JS + 类型,注解运行前被剥掉」,而 enum 违反了这个规则 (在纯 JS 运行环境直接语法报错),还带来一堆历史坑。现代实践更推荐 as const 对象 + 联合类型:

ts 复制代码
const STATUS = {
  loading: 'loading',
  success: 'success',
  error: 'error',
} as const

type Status = (typeof STATUS)[keyof typeof STATUS] // 'loading' | 'success' | 'error'

读法:typeof STATUS 拿到对象的类型,keyof 拿到键的联合,索引访问取到「所有值」的联合------效果和 enum 一致,但全程可剥除、和普通对象一样用。

5. 高频报错速查

报错 人话
Property 'createdAt' is missing in type ... 交叉类型要求字段全齐
Object is possibly 'undefined' 索引签名读取后没判空
Index signature for type 'string' is missing ... 对象字段类型与索引签名不兼容
Source has 3 element(s) but target allows only 2 元组长度超了
Type '"loaded"' is not assignable ... 状态值不在 as const 联合里(多半拼错)
相关推荐
vipxieliang1 小时前
JavaScript 事件循环与任务队列:从 setTimeout 到 Promise
前端·javascript
anyup_前端梦工厂1 小时前
uni-app 模板 Starter 一键清理 Skill 发布
前端·人工智能·uni-app
行者全栈架构师1 小时前
【鸿蒙心迹】冷启动从 2.8s 优化到 0.9s——耗时拆解与数据对比实战(HarmonyOS 7.x)
前端·算法·架构
临期冰淇淋2 小时前
MTK平台 安卓16 GMS报错修改
android·java·前端
Misnearch2 小时前
React中的回调
前端·javascript·react.js
Profile排查笔记2 小时前
浏览器多开怎么设置独立 IP?Profile、代理与核验流程
前端·人工智能·后端·自动化
anyup_前端梦工厂2 小时前
将uni-app工程迁移uni-app x,AI 能帮我们做什么?
前端·人工智能·uni-app
凌云若寒3 小时前
BarTender官网下载打印机驱动
运维·服务器·前端·网络·产品经理
zd8451015003 小时前
基于 HTML 与 Modbus TCP 构建设备仪器上位机:可行性分析与代码结构设计
前端·tcp/ip·html