引言 TypeScript 5.8是JavaScript超集语言的又一次重大进化。在这个版本中,我们看到了装饰器标准的最终落地、类型系统的进一步增强、编译性能的显著提升,以及开发者体验的全面改进。本文将深入探讨TypeScript 5.8的所有重要新特性。
一、装饰器标准化 1.1 装饰器基础 TypeScript 5.8完全采用了ECMAScript装饰器标准,这意味着TypeScript装饰器现在与JavaScript原生装饰器完全兼容。
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 // 基本类装饰器 @logged class MyClass { @format name: string constructor(name: string) { this.name = name } @validate method(@required param: string) { return param } } // 日志装饰器 function logged<T extends { new (...args: any[]): {} }>( constructor: T, context: ClassDecoratorContext ) { return class extends constructor { constructor(...args: any[]) { console.log(`Creating instance of ${constructor.name}`) super(...args) } } } // 格式化装饰器 function format( target: undefined, context: ClassFieldDecoratorContext ) { context.addInitializer(function() { console.log(`Field ${context.name} initialized`) }) } 1.2 装饰器上下文API 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 // 完整的装饰器上下文 function myDecorator( value: unknown, context: { kind: 'class' | 'method' | 'field' | 'getter' | 'setter' name: string | symbol access: { get?: () => unknown set?: (value: unknown) => void has?: (key: PropertyKey) => boolean } private?: boolean static?: boolean addInitializer?: (fn: () => void) => void metadata?: Record<string, unknown> } ) { // 根据kind执行不同逻辑 switch (context.kind) { case 'method': console.log(`Method decorator: ${String(context.name)}`) break case 'field': console.log(`Field decorator: ${String(context.name)}`) break case 'class': console.log(`Class decorator`) break } return value } 1.3 实用装饰器示例 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 55 56 57 58 59 60 61 62 63 64 // 自动绑定装饰器 function autobind( target: undefined, context: ClassMethodDecoratorContext ) { context.addInitializer(function() { const method = this[context.name] this[context.name] = method.bind(this) }) } // 记忆化装饰器 function memoize<Args extends unknown[], Result>( target: (this: any, ...args: Args) => Result, context: ClassMethodDecoratorContext ) { const cache = new Map<string, Result>() return function(this: any, ...args: Args): Result { const key = JSON.stringify(args) if (cache.has(key)) { return cache.get(key)! } const result = target.apply(this, args) cache.set(key, result) return result } } // 防抖装饰器 function debounce(ms: number) { return function<Args extends unknown[], Result>( target: (this: any, ...args: Args) => Result, context: ClassMethodDecoratorContext ) { let timeout: NodeJS.Timeout | undefined return function(this: any, ...args: Args) { clearTimeout(timeout!) timeout = setTimeout(() => { target.apply(this, args) }, ms) } } } // 使用示例 class UserService { @autobind handleClick() { console.log('Button clicked', this) } @memoize async fetchUser(id: string) { const response = await fetch(`/api/users/${id}`) return response.json() } @debounce(300) search(query: string) { console.log('Searching:', query) } } 二、类型系统增强 2.1 精确的字符串类型推断 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // TypeScript 5.8改进的字符串推断 const name = "Alice" as string // 推断为 "Alice" 而不是 string // 模板字面量类型增强 type EventName<T extends string> = `on${Capitalize<T>}` type Events = EventName<'click' | 'submit' | 'load'> // "onClick" | "onSubmit" | "onLoad" // 模板字面量类型改进 type Path<K extends string> = `pages/${K}.vue` type PagePaths = Path<'index' | 'about' | 'contact'> // "pages/index.vue" | "pages/about.vue" | "pages/contact.vue" 2.2 条件类型改进 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // 更精确的条件类型推断 type Flatten<T> = T extends Array<infer U> ? U : T type Str = Flatten<string[]> // string type Num = Flatten<number> // number // 多层条件类型 type DeepFlatten<T> = T extends Array<infer U> ? U extends Array<infer V> ? DeepFlatten<V> : U : T type Nested = DeepFlatten<number[][][]> // number // 条件类型分发改进 type ToArray<T> = T extends any ? T[] : never type Result = ToArray<string | number> // string[] | number[] 2.3 infer增强 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // 多个infer推断 type FirstLast<T extends any[]> = T extends [infer First, ...any[], infer Last] ? [First, Last] : never type FL = FirstLast<[1, 2, 3, 4, 5]> // [1, 5] // 条件infer type UnwrapPromise<T> = T extends Promise<infer U> ? U extends Promise<any> ? UnwrapPromise<U> : U : T type AsyncData = UnwrapPromise<Promise<Promise<string>>> // string // infer with rest type Tail<T extends any[]> = T extends [any, ...infer Rest] ? Rest : never type T = Tail<[1, 2, 3]> // [2, 3] 三、泛型约束增强 3.1 更强大的类型守卫 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // 类型谓词改进 function isString(value: unknown): value is string { return typeof value === 'string' } // 更精确的守卫 function isArray<T>(value: unknown): value is T[] { return Array.isArray(value) } // 带约束的守卫 function isKeyValue<T extends object>( value: unknown, key: string ): value is T & Record<string, unknown> { return typeof value === 'object' && value !== null && key in value } 3.2 模板字面量泛型约束 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 // 严格的事件名称约束 type EventHandlers = { click: (event: MouseEvent) => void focus: (event: FocusEvent) => void blur: (event: FocusEvent) => void } function on<K extends keyof EventHandlers>( event: K, handler: EventHandlers[K] ) { // 类型安全的事件绑定 } on('click', (e) => { console.log(e.clientX) // 类型为 MouseEvent }) on('unknown', (e) => {}) // 类型错误 3.3 递归类型约束 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 // JSON类型定义 type JSONValue = | string | number | boolean | null | JSONValue[] | { [key: string]: JSONValue } // 深度只读 type DeepReadonly<T> = { readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P] } // 深度必选 type DeepRequired<T> = { [P in keyof T]-?: T[P] extends object ? DeepRequired<T[P]> : T[P] } // 使用 const data: DeepReadonly<{ user: { name: string posts: { title: string }[] } }> = { user: { name: 'Alice', posts: [{ title: 'Hello' }] } } data.user.name = 'Bob' // 错误:只读属性 四、模块解析改进 4.1 更好的import类型推导 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // 动态导入类型推导 async function loadModule(path: string) { const module = await import(path) // module类型正确推导为 any // 5.8改进:可以通过类型断言获得更精确类型 return module as { default: () => void } } // 重新导出类型推导 export * from './types' export { default } from './App' export type { MyType } from './types' // 导入类型断言 import { something } from './module' import type { SomeType } from './types' 4.2 条件类型导入 1 2 3 4 5 6 7 8 9 10 11 12 13 // 环境相关的导入 if (typeof window !== 'undefined') { const { browserAPI } = await import('./browser') } else { const { nodeAPI } = await import('./node') } // 类型安全的条件导入 type API = typeof import('./api').default async function getAPI(): Promise<API> { return import('./api').then(m => m.default) } 4.3 package.json exports 1 2 3 4 5 6 7 8 9 10 11 12 13 14 { "name": "my-package", "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.mjs", "require": "./dist/index.cjs" }, "./utils": { "types": "./dist/utils.d.ts", "import": "./dist/utils.mjs" } } } 1 2 3 // 使用条件导出 import { myFunction } from 'my-package' import { myUtil } from 'my-package/utils' 五、性能优化 5.1 编译速度提升 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 // tsconfig.json 性能优化 { "compilerOptions": { // 增量编译 "incremental": true, "tsBuildInfoFile": ".tsbuildinfo", // 项目引用 "composite": true, // 跳过类型检查(仅类型) "skipLibCheck": true, // 更快的模块解析 "moduleResolution": "bundler", // 禁用声明生成(开发时) "declaration": false, "declarationMap": false } } 5.2 监听模式改进 1 2 3 4 5 # 更快的文件监听 tsc --watch # 增量编译 tsc --build --watch 5.3 项目引用优化 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 // tsconfig.base.json { "compilerOptions": { "strict": true, "skipLibCheck": true } } // tsconfig.app.json { "extends": "./tsconfig.base.json", "compilerOptions": { "outDir": "./dist/app" }, "include": ["src/**/*"], "references": [ { "path": "./tsconfig.utils.json" } ] } // tsconfig.utils.json { "extends": "./tsconfig.base.json", "compilerOptions": { "outDir": "./dist/utils", "composite": true }, "include": ["utils/**/*"] } 六、开发体验改进 6.1 更好的错误提示 1 2 3 4 5 6 7 8 9 10 11 12 13 // 更清晰的类型错误 function process(value: string | number) { if (typeof value === 'string') { return value.toUpperCase() } // TypeScript 5.8:更准确的剩余类型提示 return value.toFixed(2) // 自动推断为 number } // 链式类型错误提示 const result = JSON.parse(data) // 之前:仅提示 any // 5.8:显示完整的类型推导链 6.2 自动导入建议 1 2 3 4 5 6 7 8 9 10 // 在tsconfig.json中启用 { "compilerOptions": { "types": ["node", "jest", "vite/client"] } } // 编辑器自动建议导入 import { useState } from 'react' // 自动建议 import { ref } from 'vue' // 自动建议 6.3 代码修复建议 1 2 3 4 5 6 7 8 9 10 // 自动修复建议 const user: User = { name: 'Alice', // age: 25 // 缺少必填属性 // TypeScript 5.8:一键添加缺失属性 } // 类型转换建议 const value = getData() as string // 建议使用类型守卫 七、高级类型模式 7.1 品牌类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // 品牌类型模式 type Brand<T, B> = T & { __brand: B } type USD = Brand<number, 'USD'> type EUR = Brand<number, 'EUR'> const usd = (amount: number): USD => amount as USD const eur = (amount: number): EUR => amount as EUR function addUSD(a: USD, b: USD): USD { return usd(a + b) } addUSD(usd(10), usd(20)) // ✅ addUSD(usd(10), eur(20)) // ❌ 类型错误 7.2 状态机类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 type State = | { status: 'idle' } | { status: 'loading'; startTime: number } | { status: 'success'; data: string } | { status: 'error'; error: Error } function processState(state: State) { switch (state.status) { case 'idle': return 'Initial state' case 'loading': return `Started at ${state.startTime}` // 类型安全 case 'success': return `Data: ${state.data}` // 类型安全 case 'error': return `Error: ${state.error.message}` // 类型安全 } } 7.3 函数重载类型 1 2 3 4 5 6 7 8 9 10 11 12 // 函数重载 function process(input: string): string function process(input: number): number function process(input: string | number): string | number { if (typeof input === 'string') { return input.toUpperCase() } return input * 2 } const result1 = process('hello') // string const result2 = process(42) // number 八、实用工具类型 8.1 内置工具类型 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 // Partial<T> - 所有属性可选 type PartialUser = Partial<User> // Required<T> - 所有属性必填 type RequiredUser = Required<Partial<User>> // Readonly<T> - 只读 type ReadonlyUser = Readonly<User> // Pick<T, K> - 选择属性 type UserBasic = Pick<User, 'name' | 'email'> // Omit<T, K> - 排除属性 type UserPrivate = Omit<User, 'password'> // Record<K, T> - 构建类型 type Users = Record<string, User> // Exclude<T, U> - 排除类型 type Numbers = Exclude<string | number, string> // Extract<T, U> - 提取类型 type Strings = Extract<string | number, string> // NonNullable<T> - 排除null/undefined type Defined = NonNullable<string | null | undefined> 8.2 自定义工具类型 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 // 深度Partial type DeepPartial<T> = { [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P] } // 深度Omit type DeepOmit<T, K extends string> = { [P in keyof T as P extends K ? never : P]: T[P] } // 获取函数返回类型 type ReturnType<T extends (...args: any) => any> = T extends ( ...args: any ) => infer R ? R : any // 获取函数参数类型 type Parameters<T extends (...args: any) => any> = T extends ( ...args: infer P ) => any ? P : never 总结 TypeScript 5.8带来了显著的改进:
...