0192. 索引访问类型
1. 🎯 本节内容
- 索引访问类型的基本概念和语法
- 索引访问类型的使用方法
- 联合类型的分发机制
2. 🫧 评价
TS 中的索引访问类型是一种通过索引获取其他类型的子类型的机制。
相关笔记:0101. 对象索引签名
3. 🤔 索引访问类型是什么?
索引访问类型允许通过索引获取另一个类型的子类型。
- 索引访问类型使用
T[K]语法访问类型T中键K对应的类型 - 索引是指
string | number | symbol类型,或者它们的子类型 - 可以与
keyof、联合类型等其他类型特性结合使用 - 支持嵌套访问,可以深入获取复杂结构中的类型
ts
// 基本语法:Type[Key]
// 作用:获取 Type 类型中 Key 对应的类型
interface Person {
name: string
age: number
email: string
}
type NameType = Person['name'] // string
type AgeType = Person['age'] // number
type EmailType = Person['email'] // string1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
索引访问类型是类型层面的操作,不能和运行时的值操作混用。
ts
interface Product {
id: number
name: string
price: number
}
// TS 类型层面:访问类型
type ProductName = Product['name'] // string
// JS 值层面:访问属性值
const product: Product = { id: 1, name: 'Book', price: 20 }
const productName = product['name'] // 'Book'
const obj = { x: 10, y: 20 }
// ❌ 错误:类型和值不能混用
// type Wrong = obj['x'] // ❌ Error - 'obj' 仅表示值,但在此处用作类型
// 'obj' refers to a value, but is being used as a type here. Did you mean 'typeof obj'?(2749)
// ✅ 正确:使用 typeof 将值转为类型
type XType = (typeof obj)['x'] // number
// ❌ 错误:类型和值不能混用
// const key = 'x'
// type Wrong2 = (typeof obj)[key] // ❌ Error - key 是值层面的
// Type 'key' cannot be used as an index type.(2538)
// ✅ 正确:使用 typeof 将值转为类型
const key = 'x'
type XType2 = (typeof obj)[typeof key] // number1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
4. 🤔 索引访问类型如何使用?
索引访问通常用于以下这些类型:
- 访问对象属性类型
- 访问数组元素类型
- 访问元组元素类型
ts
// 基本属性访问:
interface User {
id: number
name: string
email: string
isActive: boolean
}
type UserId = User['id'] // number
type UserName = User['name'] // string
type UserEmail = User['email'] // string
type IsActive = User['isActive'] // boolean
// 访问可选属性:
interface Config {
host: string
port: number
ssl?: boolean
}
type SSLType = Config['ssl'] // boolean | undefined
// 访问只读属性:
interface ReadonlyData {
readonly id: number
readonly created: Date
}
type IdType = ReadonlyData['id'] // number (readonly 在类型中不保留)
type CreatedType = ReadonlyData['created'] // Date1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
ts
// 普通数组:
type StringArray = string[]
type StringArrayElement = StringArray[number] // string
type NumberArray = number[]
type NumberArrayElement = NumberArray[number] // number
// 混合类型数组:
type MixedArray = (string | number)[]
type MixedElement = MixedArray[number] // string | number
// 对象数组:
type UserArray = Array<{ id: number; name: string }>
type UserElement = UserArray[number]
// type UserElement = { id: number; name: string; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ts
// 按索引访问:
type Tuple = [string, number, boolean]
type First = Tuple[0] // string
type Second = Tuple[1] // number
type Third = Tuple[2] // boolean
// 使用 number 访问所有元素:
type TupleElement = Tuple[number] // string | number | boolean
// 具名元组:这个名称只起到一个语义提示的作用,没有任何实际作用,当名称不存在即可。
type NamedTuple = [name: string, age: number, active: boolean]
type NameType = NamedTuple[0] // string
type AgeType = NamedTuple[1] // number
type AllTypes = NamedTuple[number] // string | number | boolean1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
一些常见的高级用法:
- 使用联合类型索引访问多个属性
- 结合 keyof 使用
- 嵌套索引访问
ts
interface User {
id: number
name: string
email: string
age: number
}
type UserStringFields = User['name' | 'email'] // string
type UserIdOrAge = User['id' | 'age'] // number
type AllFields = User['id' | 'name' | 'email' | 'age'] // string | number
// AllFields 的获取可以利用 keyof 简写:
type AllFields2 = User[keyof User] // string | number1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
ts
// 获取所有属性值类型的联合:
interface Person {
name: string
age: number
email: string
}
type PersonValue = Person[keyof Person] // string | number
// 泛型函数中的应用:
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key]
}
const person = { name: 'Alice', age: 25 }
const person_name = getProperty(person, 'name') // string
const person_age = getProperty(person, 'age') // number
// 复杂示例:
interface Data {
id: number
name: string
metadata: {
created: Date
updated: Date
}
}
type ValueTypes = Data[keyof Data]
// type ValueTypes = number | string | { created: Date; updated: Date; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
ts
// 多层访问:
interface Organization {
name: string
address: {
street: string
city: string
country: {
name: string
code: string
}
}
}
type AddressType = Organization['address']
// type AddressType = {
// street: string;
// city: string;
// country: {
// name: string;
// code: string;
// };
// }
type CityType = Organization['address']['city']
// type CityType = string
type CountryNameType = Organization['address']['country']['name']
// type CountryNameType = string
// 数组嵌套访问:
interface Company {
departments: Array<{
name: string
employees: Array<{
id: number
name: string
}>
}>
}
type DepartmentType = Company['departments'][number]
// type DepartmentType = {
// name: string;
// employees: Array<{
// id: number;
// name: string;
// }>;
// }
type EmployeeType = Company['departments'][number]['employees'][number]
// type EmployeeType = {
// id: number;
// name: string;
// }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
注意:联合类型的分发机制
ts
interface A {
x: string
y: number
}
interface B {
x: number
z: boolean
}
type Union = A | B
type XType = Union['x'] // string | number (分发到两个类型)1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12