TypeScript中如何让泛型参数无需按固定顺序传递?
实现方案
可以通过「收拢分散泛型参数为单个配置对象类型」的方式,实现类似命名传参的效果,无需按顺序传递泛型,仅指定需要自定义的字段即可,其余字段自动使用预设默认值。
第一步:定义统一的泛型配置接口
首先把所有泛型参数收拢到一个接口里,同时设置通用默认值:
interface MiddlewareOptions { Store: never Args: unknown Response: unknown // 后续新增泛型参数直接在这里加即可,不会影响原有使用逻辑 }
第二步:写泛型合并工具(简化代码)
写一个通用工具类型,自动合并用户传入的自定义配置和默认配置:
// 作用:用户传了的字段用用户的,没传的用默认值 type MergeDefault<T, Default> = T & Omit<Default, keyof T>
第三步:改造原Middleware类型
把原来的多泛型参数改为单泛型接收配置对象:
export type Middleware<T extends Partial<MiddlewareOptions> = {}> = ( context: { endpoint: string args: MergeDefault<T, MiddlewareOptions>['Args'] locals: { store?: MergeDefault<T, MiddlewareOptions>['Store'] [key: string]: unknown } } ) => Promise<MergeDefault<T, MiddlewareOptions>['Response'] | void> | MergeDefault<T, MiddlewareOptions>['Response'] | void
使用示例
无需记忆泛型顺序,按需指定需要自定义的字段即可:
- 仅自定义Args类型,其余用默认值:
// 等价于原写法 Middleware<never, { id: number }, unknown>,无需手动补前置的never type GetUserMiddleware = Middleware<{ Args: { id: number } }>
- 仅自定义Response和Store,跳过Args:
// 等价于原写法 Middleware<{ uid: string }, unknown, { code: number; data: any }> type CommonMiddleware = Middleware<{ Response: { code: number; data: any }, Store: { uid: string } }>
方案优势
- 完全不依赖泛型传参顺序,不需要手动填写不需要的前置泛型值
- 后续新增泛型配置仅需在
MiddlewareOptions中新增字段并设置默认值,旧的使用代码无需任何改动,兼容性极强 - 字段名语义化,不需要记忆泛型位置,开发体验更好
内容的提问来源于stack exchange,提问作者shennan
相关产品推荐
相关产品推荐

