前端开发

TypeScript 高级特性详解

2024-01-05
15 分钟

TypeScript 高级特性详解

TypeScript 不仅仅是 JavaScript 的类型系统,它还提供了许多高级特性来帮助我们编写更安全、更可维护的代码。

泛型 (Generics)

基础泛型

泛型允许我们创建可重用的组件,这些组件可以处理多种类型:

```typescript
function identity(arg: T): T {
return arg
}

// 使用
const stringResult = identity("hello")
const numberResult = identity(42)
```

泛型约束

使用 extends 关键字约束泛型类型:

```typescript
interface Lengthwise {
length: number
}

function loggingIdentity(arg: T): T {
console.log(arg.length) // 现在我们知道它有 length 属性
return arg
}

loggingIdentity("hello") // ✅ 字符串有 length 属性
loggingIdentity([1, 2, 3]) // ✅ 数组有 length 属性
// loggingIdentity(3) // ❌ 数字没有 length 属性
```

条件类型

根据条件选择不同的类型:

```typescript
type NonNullable = T extends null | undefined ? never : T

type A = NonNullable<string | null> // string
type B = NonNullable<number | undefined> // number

// 更复杂的条件类型
type ApiResponse = T extends string
? { message: T }
: T extends number
? { code: T }
: { data: T }

type StringResponse = ApiResponse // { message: string }
type NumberResponse = ApiResponse // { code: number }
type ObjectResponse = ApiResponse<{ id: number }> // { data: { id: number } }
```

映射类型

基础映射类型

基于现有类型创建新类型:

```typescript
type Readonly = {
readonly [P in keyof T]: T[P]
}

type Partial = {
[P in keyof T]?: T[P]
}

interface User {
id: number
name: string
email: string
}

type ReadonlyUser = Readonly
// {
// readonly id: number
// readonly name: string
// readonly email: string
// }

type PartialUser = Partial
// {
// id?: number
// name?: string
// email?: string
// }
```

自定义映射类型

```typescript
// 将所有属性转换为字符串类型
type Stringify = {
[K in keyof T]: string
}

// 选择特定属性
type Pick<T, K extends keyof T> = {
[P in K]: T[P]
}

// 排除特定属性
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>

interface User {
id: number
name: string
email: string
password: string
}

type PublicUser = Omit<User, 'password'>
// {
// id: number
// name: string
// email: string
// }
```

工具类型

常用工具类型

```typescript
interface User {
id: number
name: string
email: string
age?: number
}

// Required - 使所有属性必需
type RequiredUser = Required

// Record - 创建对象类型
type UserRoles = Record<string, User>

// Extract - 提取联合类型中的特定类型
type StringOrNumber = string | number | boolean
type OnlyStringOrNumber = Extract<StringOrNumber, string | number> // string | number

// Exclude - 排除联合类型中的特定类型
type WithoutBoolean = Exclude<StringOrNumber, boolean> // string | number

// ReturnType - 获取函数返回类型
function getUser(): User {
return { id: 1, name: "John", email: "john@example.com" }
}

type UserReturnType = ReturnType // User
```

模板字面量类型

基础模板字面量

```typescript
type World = "world"
type Greeting = hello ${World} // "hello world"

// 联合类型的组合
type Color = "red" | "green" | "blue"
type Size = "small" | "medium" | "large"
type Style = ${Color}-${Size} // "red-small" | "red-medium" | ... | "blue-large"
```

实际应用

```typescript
// API 路径类型
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE"
type ApiPath = "/users" | "/posts" | "/comments"
type ApiEndpoint = ${HttpMethod} ${ApiPath}

// CSS 属性类型
type CSSProperty = "margin" | "padding"
type CSSDirection = "top" | "right" | "bottom" | "left"
type CSSPropertyWithDirection = ${CSSProperty}-${CSSDirection}
// "margin-top" | "margin-right" | ... | "padding-left"

// 事件处理器类型
type EventName = "click" | "hover" | "focus"
type EventHandler = on${Capitalize<T>}

type ClickHandler = EventHandler<"click"> // "onClick"
type HoverHandler = EventHandler<"hover"> // "onHover"
```

装饰器 (Decorators)

类装饰器

```typescript
function sealed(constructor: Function) {
Object.seal(constructor)
Object.seal(constructor.prototype)
}

@sealed
class Greeter {
greeting: string
constructor(message: string) {
this.greeting = message
}
greet() {
return Hello, ${this.greeting}
}
}
```

方法装饰器

```typescript
function log(target: any, propertyName: string, descriptor: PropertyDescriptor) {
const method = descriptor.value

descriptor.value = function (...args: any[]) {
console.log(调用方法 ${propertyName},参数:, args)
const result = method.apply(this, args)
console.log(方法 ${propertyName} 返回:, result)
return result
}
}

class Calculator {
@log
add(a: number, b: number): number {
return a + b
}
}
```

高级类型技巧

递归类型

```typescript
// 深度只读
type DeepReadonly = {
readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P]
}

// 深度可选
type DeepPartial = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P]
}

interface NestedObject {
a: {
b: {
c: string
}
}
}

type ReadonlyNested = DeepReadonly
// {
// readonly a: {
// readonly b: {
// readonly c: string
// }
// }
// }
```

类型推断

```typescript
// 推断数组元素类型
type ArrayElement = T extends (infer U)[] ? U : never

type StringArray = string[]
type ElementType = ArrayElement // string

// 推断函数参数类型
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never

function example(a: string, b: number): void {}
type ExampleParams = Parameters // [string, number]

// 推断 Promise 类型
type Awaited = T extends Promise ? U : T

type PromiseString = Promise
type StringType = Awaited // string
```

实际应用示例

类型安全的 API 客户端

```typescript
interface ApiEndpoints {
'/users': {
GET: { response: User[] }
POST: { body: Omit<User, 'id'>; response: User }
}
'/users/:id': {
GET: { params: { id: string }; response: User }
PUT: { params: { id: string }; body: Partial; response: User }
DELETE: { params: { id: string }; response: void }
}
}

class ApiClient {
async request<
Path extends keyof ApiEndpoints,
Method extends keyof ApiEndpoints[Path]

(
path: Path,
method: Method,
options?: ApiEndpoints[Path][Method] extends { body: any }
? { body: ApiEndpoints[Path][Method]['body'] }
: ApiEndpoints[Path][Method] extends { params: any }
? { params: ApiEndpoints[Path][Method]['params'] }
: {}
): Promise<ApiEndpoints[Path][Method]['response']> {
// 实现细节...
return {} as any
}
}

const client = new ApiClient()

// 类型安全的 API 调用
const users = await client.request('/users', 'GET') // User[]
const user = await client.request('/users/:id', 'GET', { params: { id: '1' } }) // User
const newUser = await client.request('/users', 'POST', {
body: { name: 'John', email: 'john@example.com' }
}) // User
```

总结

TypeScript 的高级特性为我们提供了强大的类型系统工具:

  • 泛型: 创建可重用的类型安全组件
  • 条件类型: 根据条件选择不同类型
  • 映射类型: 基于现有类型创建新类型
  • 模板字面量: 创建动态字符串类型
  • 装饰器: 为类和方法添加元数据和行为

掌握这些高级特性,能够让你编写更加类型安全、可维护的 TypeScript 代码!
```