第 1 节 概述
上一篇我们认识了基础类型:string、number、boolean……
但现实中的数据往往是"或"、“且"的关系——“这个值可以是字符串或数字”、“这个人必须有姓名和年龄”。
TypeScript 的类型系统支持类型运算。就像数字能做加减乘除一样,类型之间也可以组合和变换。
第 2 节 联合类型
联合类型用 | 表示"或”。一个值可以是几种类型中的任意一种:
1
2
3
4
5
| let id: string | number
id = "abc-123" // ✅
id = 42 // ✅
id = true // ❌ boolean 不在联合中
|
最常见的用法是搭配字面量类型,限定一组可选值:
1
2
3
4
5
6
7
8
| type Direction = "up" | "down" | "left" | "right"
function move(direction: Direction) {
// direction 只能是这四个值之一
}
move("up") // ✅
move("back") // ❌ 不在允许范围内
|
函数的可选参数也可以用到联合类型。比如一个参数既可以是 string,也可以是 string[]:
1
2
3
4
5
6
| function format(input: string | string[]) {
if (Array.isArray(input)) {
return input.join(", ")
}
return input
}
|
第 3 节 交叉类型
交叉类型用 & 表示"且"。一个值同时满足所有条件:
1
2
3
4
5
6
7
8
9
10
| type HasName = { name: string }
type HasAge = { age: number }
type Person = HasName & HasAge
const person: Person = {
name: "张三",
age: 18,
}
// 必须同时有 name 和 age
|
注意
如果交叉的类型有同名但类型不同的属性,会产生 never:
1
2
3
| type A = { x: string }
type B = { x: number }
type C = A & B // x 的类型是 string & number → never
|
第 4 节 type 别名
type 可以为任意类型起一个名字。它不创建新类型,只是给现有类型一个别名:
1
2
3
4
5
| type Name = string
type Age = number
const myName: Name = "张三"
const myAge: Age = 18
|
它的真正价值在于给复杂类型一个有意义的名字:
1
2
3
4
5
6
7
8
9
10
11
| type Point = {
x: number
y: number
}
type Status = "idle" | "loading" | "success" | "error"
type ApiResponse<T> = {
data: T
status: Status
}
|
用 type 定义的类型,可以在任何地方引用,避免重复书写。
第 5 节 keyof 操作符
keyof 取出一个对象类型的所有键,组成联合类型:
1
2
3
4
5
6
7
8
| type Person = {
name: string
age: number
email: string
}
type PersonKeys = keyof Person
// 等价于 "name" | "age" | "email"
|
实际用途:限制函数参数只能是对象的某个键:
1
2
3
4
5
6
7
| function getValue<T>(obj: T, key: keyof T) {
return obj[key]
}
const person = { name: "张三", age: 18 }
getValue(person, "name") // ✅
getValue(person, "gender") // ❌ "gender" 不在 keyof 中
|
第 6 节 typeof 操作符
typeof 在类型上下文中,获取一个值的 TypeScript 类型:
1
2
3
4
5
6
7
| const person = {
name: "张三",
age: 18,
}
type PersonType = typeof person
// 等价于 { name: string; age: number }
|
这在处理已有数据时非常有用,不用手动再写一遍类型:
1
2
3
4
5
6
7
8
9
10
11
12
| const config = {
url: "https://api.example.com",
timeout: 5000,
retry: true,
}
type Config = typeof config
// { url: string; timeout: number; retry: boolean }
function fetchData(config: Config) {
// ...
}
|
技巧
typeof 和 keyof 经常搭配使用:keyof typeof config 可以拿到配置对象的所有键。
第 7 节 索引访问类型
你可以像访问对象属性那样,访问类型的某个属性的类型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| type Person = {
name: string
age: number
address: {
city: string
street: string
}
}
type NameType = Person["name"]
// string
type AddressType = Person["address"]
// { city: string; street: string }
type NameOrAge = Person["name" | "age"]
// string | number
|
甚至可以传入一个类型作为索引:
1
2
3
| type PersonKeys = keyof Person // "name" | "age" | "address"
type Values = Person[keyof Person]
// string | number | { city: string; street: string }
|
这一篇我们学会了组合类型。就像是学会了加法和乘法——你能用基础类型的砖块,搭出更复杂的结构。
有了这些工具,我们可以描述更真实的数据了。 下一篇看看数组和元组——如何给"一组数据"加上类型。