概述 Typescript 的高级类型指操作基本类型和复合类型而得的类型,包括: 联合 交叉 泛型 类型别名 在讲具体的高级类型之前,我们先了解一下 Typescript 的类型别名。类型别名也是一种类型,…

一、TypeScript高级类型

1.1 概述

Typescript 的高级类型指操作基本类型和复合类型而得的类型,包括:

联合
交叉
泛型

1.2 类型别名

在讲具体的高级类型之前,我们先了解一下 Typescript 的类型别名。类型别名也是一种类型,用一个单词代表可能比较复杂的类型声明,用关键字
type
表示。
示例:

1
2
3
4
5
6
7
8
9
  type S = string

let a: S = 'a'

`这里用```text
S
`作为```text
string
`的别名,使用方法和```text

一模一样。
别名不仅可以代表基本类型,它可以代表任意类型。示例:

1
2
3
4
5
6
  type SA = string[] // 代表字符串数组
type Handler = (x: string) => void // 代表函数
type I = {
// 代表接口
name: string
value: number

}

1
2
3
class C {
name: string = 'a'
value: number = 0

}

1
type D = C // 代表类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  
#### 1.3 类型
##### 联合
联合类型是指变量为多个类型中的一种,是“或”的关系,用操作符
`|`
表示。
示例:

type StringOrNumber = string | number

let a: StringOrNumber = 'a'
let b: StringOrNumber = 0

function log(x: string | number) {
console.log(x)
}

`这里```text
StringOrNumber
`表示一种可以是字符串或者也可以是数字的类型,所以对于```text

类型的变量,既可以赋值为字符串,也可以赋值为数字。
在 Typescript 中,
null

undefined
与其它类型是同层级的,它们不是任何类型的子类型,也就是说我们不能用它们来表示一个特定类型的空指针。但是我们确实需要在一个变量未确定时保持为空状态,这时可以用联合类型来表示一个变量可为

。示例:

1
interface A {

}

1
let a: A | null = null
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  
###### 字面量类型
Typescript 中字面量也可以作为一个类型。比如:

`let a: 'A'`

上述声明表示变量
`a`
的值只能是
`'A'`
,赋值为其它值时会报错。
数字和布尔也可以作为字面量类型。这看起来没什么用,但是这种特性一般会与联合结合起来使用。比如:

type Option = 'A' | 'B' | 'C' | 'D'

let a: Option = 'A'
let e: Option = 'E' // 错误

Option
类型的变量只能被赋值为
'A'

'B'

'C'

'D'
中一个值。这一种用法和枚举很像,比如:

1
enum Option {

A,
B,
C,
D
}

`不同的是,字面量类型本质上是字符串,可以使用字符串的所有方法。而且,通过```text
keyof

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 操作符,我们可以动态的生成字面量类型,这一点将在之后介绍。 
##### 交叉
交叉类型是指多个类型合并成一个类型,是“且”的关系,用操作符
`&`
表示。
示例:

x: string
y: number
}
interface B {
z: number
}

type C = A & B

let c: C = { x: 'x', y: 0, z: 1 }

`交叉类型的成员包含了所有原类型的的所有成员,比如上述代码中,```text
c
`变量必须既是```text
A
`类型也是```text
B

类型,也就是说它必须同时拥有两个类型要求的属性。

1
有一些类型是无法交叉的,比如基本类型。示例: `type A = string & number` 因为一个变量不可能既是字符串又是数字,所以最终 

A
类型是
never
类型。
如果被交叉的两个类型有同名但类型不同的成员,那么这两个同名成员也会被交叉。示例:

1
x: { a: string; b: number }

}

1
x: { a: string; c: number }

}

1
let c: C = { x: { a: 'a', b: 0, c: 1 } }

类型```text Atext B `有同名但类型不同的成员text
x
,交叉时两个```text x成员也可以交叉,因此最终text x `的类型为:java

1
{a: string, b: number, c: number}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

##### 泛型
Typescript 中的泛型与其它面向对象语言中的泛型和相似,包括:泛型函数、泛型类和泛型接口。
###### 泛型函数
示例:

function merge<T, U>(x: T, y: U): { x: T; y: U } {
let t: { x: T; y: U } = { x, y }

return t
}

merge<string, number>('a', 0)

`我们可以在中括号内声明函数中使用到的泛型变量,它代表了在调用函数时传入的类型。类型变量```text
T

可以用在任何需要类型声明的地方,比如参数类型、返回值类型、局部变量类型等。
箭头函数也可以包含泛型。示例:

1
const merge = <T, U>(x: T, y: U): { x: T; y: U } => {

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  
###### 泛型类
示例:

class Merge<T, U> {
x: T
y: U

constructor(x: T, y: U) {
this.x = x
this.y = y
}

merge(): { x: T; y: U } {
let t: { x: T; y: U } = { x: this.x, y: this.y }

}

let merge = new Merge<string, number>()

`我们可以在中括号内声明类中使用到的泛型变量,它代表了在实例化类时传入的类型。类型变量```text
T

可以用在任何需要类型声明的地方,比如成员、构造方法参数类型等。

泛型接口

示例:

1
2
3
4
5
6
7
8
9
  interface Merge<T, U> {
x: T
y: U
}

let merge: Merge<string, number> = { x: 'a', y: 0 }

`我们可以在中括号内声明接口中使用到的泛型变量,它代表了在声明变量类型时传入的类型。类型变量```text
T

可以用在任何需要类型声明的地方,比如成员、方法参数类型等。

泛型约束

由于在泛型类型中,泛型变量是在使用时传入的,所以在编译时无法得知其具体类型,那么读取类类型变量的任何成员都是不行的。比如:

1
function scale<T>(x: T): number {

return x.length // 错误
}

虽然我们可能心里知道在使用时我们会传入一个具有```text length成的变量(比如字符串),但是在编译时编译器并不知道。因此,我们需要告诉编译器text T `类型是那一类具有text
成员的类型。使用```text extends关键字:```java

1
2
interface HasLength {
length: number

}

1
function scale<T extends HasLength>(x: T): number {

return x.length
}

1
scale('abc')

我们使用```text对类型变量text T `进行了约束,它必须具有text
`属性。也就是是说```text
T

 类型必须实现或继承了 HasLength 类型。
                                      

本文标题: Typescript小小册高级类型

发布时间: 2025年02月18日 00:00

最后更新: 2025年12月30日 08:54

原始链接: https://haoxiang.eu.org/ddd243fd/

版权声明: 本文著作权归作者所有,均采用CC BY-NC-SA 4.0许可协议,转载请注明出处!

× 喜欢就赞赏一下呗!
打赏二维码