← 返回文章列表

TypeScript高级类型技巧

2023-07-10作者: YZ12 分钟
TypeScriptJavaScript前端开发编程语言
# TypeScript高级类型技巧 TypeScript的类型系统非常强大,远超过简单的类型注解。掌握高级类型技巧可以帮助你编写更安全、更可维护的代码。本文将介绍一些TypeScript中的高级类型技术,帮助你充分利用TypeScript的类型系统。 ## 条件类型 条件类型允许你根据类型关系创建新的类型,类似于JavaScript中的条件表达式。 ### 基本语法 ```typescript type IsString = T extends string ? true : false; // 使用示例 type A = IsString; // true type B = IsString; // false ``` ### 实际应用 条件类型在处理联合类型和泛型约束时特别有用: ```typescript // 从联合类型中提取特定类型 type Extract = T extends U ? T : never; type NumberOrString = number | string | boolean; type JustNumberOrString = Extract; // 结果: number | string // 排除特定类型 type Exclude = T extends U ? never : T; type JustBoolean = Exclude; // 结果: boolean ``` ## 映射类型 映射类型允许你基于旧类型创建新类型,通过遍历现有类型的属性。 ### 基本语法 ```typescript type Readonly = { readonly [P in keyof T]: T[P]; }; // 使用示例 interface Person { name: string; age: number; } type ReadonlyPerson = Readonly; // 等同于: { readonly name: string; readonly age: number; } ``` ### 实际应用 映射类型可以用于创建工具类型,如Partial、Required等: ```typescript // 使所有属性可选 type Partial = { [P in keyof T]?: T[P]; }; // 使所有属性必需 type Required = { [P in keyof T]-?: T[P]; }; // 选取特定属性 type Pick = { [P in K]: T[P]; }; // 使用示例 interface User { id: number; name: string; email: string; address?: string; } type UserBasicInfo = Pick; // 结果: { id: number; name: string; } ``` ## 模板字面量类型 TypeScript 4.1引入了模板字面量类型,允许你基于字符串字面量类型创建新的字符串字面量类型。 ### 基本语法 ```typescript type World = 'world'; type Greeting = `Hello ${World}`; // 结果: "Hello world" ``` ### 实际应用 模板字面量类型在创建基于现有类型的字符串类型时非常有用: ```typescript // 创建CSS属性类型 type CSSProperty = 'color' | 'background-color' | 'margin'; type CSSValue = string | number; type CSSPropertyMap = { [K in CSSProperty]: CSSValue; }; // 创建事件处理器类型 type EventName = 'click' | 'change' | 'mouseenter'; type EventHandlerName = `on${Capitalize}`; // 结果: "onClick" | "onChange" | "onMouseenter" // 使用内置的字符串操作类型 type Greeting = "hello world"; type ShoutyGreeting = Uppercase; // 结果: "HELLO WORLD" type QuietGreeting = Lowercase; // 结果: "hello world" type CapitalizedGreeting = Capitalize; // 结果: "Hello world" type UncapitalizedGreeting = Uncapitalize; // 结果: "hello world" ``` ## 递归类型 TypeScript支持递归类型定义,这在处理嵌套结构时非常有用。 ### 基本示例 ```typescript // 定义嵌套数组类型 type NestedArray = Array>; const nested: NestedArray = [1, 2, [3, 4, [5, 6]]]; // 定义嵌套对象类型 type NestedObject = { value: T; children?: NestedObject[]; }; const tree: NestedObject = { value: 'root', children: [ { value: 'child1' }, { value: 'child2', children: [{ value: 'grandchild' }] } ] }; ``` ### JSON类型示例 ```typescript type JSONPrimitive = string | number | boolean | null; type JSONArray = JSONValue[]; type JSONObject = { [key: string]: JSONValue }; type JSONValue = JSONPrimitive | JSONArray | JSONObject; const json: JSONValue = { name: 'John', age: 30, isActive: true, address: { street: '123 Main St', city: 'Anytown' }, hobbies: ['reading', 'coding', { type: 'sports', favorite: 'basketball' }] }; ``` ## 类型推断与infer关键字 `infer`关键字允许你在条件类型中推断和捕获类型。 ### 基本语法 ```typescript type ReturnType = T extends (...args: any[]) => infer R ? R : any; // 使用示例 function createUser(name: string, age: number) { return { name, age }; } type User = ReturnType; // 结果: { name: string; age: number; } ``` ### 实际应用 `infer`在提取复杂类型的组件时非常有用: ```typescript // 提取Promise的值类型 type UnwrapPromise = T extends Promise ? U : T; type Result = UnwrapPromise>; // 结果: string // 提取函数参数类型 type Parameters = T extends (...args: infer P) => any ? P : never; type Params = Parameters<(a: number, b: string) => void>; // 结果: [number, string] // 提取构造函数的实例类型 type InstanceType = T extends new (...args: any[]) => infer R ? R : any; class Person { name: string; constructor(name: string) { this.name = name; } } type PersonInstance = InstanceType; // 结果: Person ``` ## 联合类型的分布式条件类型 当在泛型中使用条件类型时,联合类型会被分布处理。 ```typescript type ToArray = T extends any ? T[] : never; type NumberOrStringArray = ToArray; // 结果: number[] | string[] // 而不是: (number | string)[] // 如果要避免分布式行为 type ToArrayNonDist = [T] extends [any] ? T[] : never; type NumberOrStringArrayNonDist = ToArrayNonDist; // 结果: (number | string)[] ``` ## 类型体操示例 以下是一些展示TypeScript类型系统强大功能的高级示例: ### 深度Readonly ```typescript type DeepReadonly = { readonly [P in keyof T]: T[P] extends object ? T[P] extends Function ? T[P] : DeepReadonly : T[P]; }; interface User { id: number; name: string; settings: { theme: string; notifications: { email: boolean; sms: boolean; }; }; } type ReadonlyUser = DeepReadonly; // 所有嵌套属性都是只读的 ``` ### 类型安全的事件发射器 ```typescript type EventMap = { click: { x: number; y: number }; change: { value: string }; submit: { data: Record }; }; class TypedEventEmitter> { private listeners: { [E in keyof Events]?: Array<(data: Events[E]) => void>; } = {}; on(event: E, listener: (data: Events[E]) => void) { if (!this.listeners[event]) { this.listeners[event] = []; } this.listeners[event]!.push(listener); return this; } emit(event: E, data: Events[E]) { if (!this.listeners[event]) return false; this.listeners[event]!.forEach(listener => listener(data)); return true; } } const emitter = new TypedEventEmitter(); // 类型安全的事件监听 emitter.on('click', data => { console.log(`Clicked at ${data.x}, ${data.y}`); }); // 类型错误: 参数类型不匹配 // emitter.emit('click', { value: 'wrong' }); // 正确用法 emitter.emit('click', { x: 10, y: 20 }); ``` ## 结论 TypeScript的类型系统非常强大,掌握这些高级类型技巧可以帮助你编写更安全、更可维护的代码。通过条件类型、映射类型、模板字面量类型、递归类型和类型推断,你可以创建复杂而精确的类型定义,捕获更多潜在错误,并提供更好的开发体验。 随着对这些技术的深入理解,你将能够充分利用TypeScript的类型系统,创建更加健壮的应用程序。

相关文章

React 18中的新特性与性能优化

React 18带来了许多令人兴奋的新特性,包括并发渲染、自动批处理和Suspense的改进。本文将深入探讨这些特性以及如何利用它们优化你的React应用性能。

使用Next.js构建SEO友好的网站

Next.js提供了强大的SEO优化功能,本文将介绍如何利用这些功能构建对搜索引擎友好的网站,包括服务器端渲染、静态生成和元数据管理等技术。