TypeScript:为泛型SQL函数封装默认泛型类型的实现问询
问题解答
1. 当前实现是否正确?
你的实现完全正确。
insertQuery通过Parameters<typeof executeQuery>完整继承了executeQuery的参数类型,同时将泛型Result的默认值设为OkPacket,既复用了核心查询逻辑,又实现了不同操作场景下的默认类型区分。从你提供的类型验证示例来看,VSCode能正确推导packet为OkPacket、numberPacket为number,说明类型约束完全生效,符合预期。
2. 是否有更简便的实现方案?
当前封装方案已经轻量简洁,不过可以根据需求考虑以下替代方案:
方案一:函数重载
无需单独封装insertQuery,直接给executeQuery添加重载签名,区分查询和插入场景的默认返回类型:
// 查询操作默认返回 RowDataPacket[] async function executeQuery( event: CompatibilityEvent, query: string, values?: any[], onError?: ErrorEmitter ): Promise<[RowDataPacket[], FieldPacket[]]>; // 插入操作可指定泛型,默认返回 OkPacket async function executeQuery<Result = OkPacket>( event: CompatibilityEvent, query: string, values?: any[], onError?: ErrorEmitter ): Promise<[Result, FieldPacket[]]>; // 核心实现 async function executeQuery<Result = RowDataPacket[]>( event: CompatibilityEvent, query: string, values: any[] = [], onError: ErrorEmitter ): Promise<[Result, FieldPacket[]]> { // 原有逻辑 }
这种方式省去了额外的包装函数,但需要调用者明确场景(或通过泛型指定),可读性不如单独封装insertQuery直观。
方案二:语义化类型别名
通过类型别名强化不同操作的返回类型语义,保持现有包装函数不变:
type QueryResult<T = RowDataPacket[]> = [T, FieldPacket[]]; type InsertResult<T = OkPacket> = QueryResult<T>; // 修改 executeQuery 返回类型 export async function executeQuery<Result = RowDataPacket[]>( event: CompatibilityEvent, query: string, values: any[] = [], onError: ErrorEmitter ): Promise<QueryResult<Result>> { // 原有逻辑 } export function insertQuery<Result = OkPacket>(...params: Parameters<typeof executeQuery>) { return executeQuery<Result>(...params) as Promise<InsertResult<Result>>; }
这种方式仅优化了类型的可读性,核心逻辑和原有方案一致。
3. TypeScript是否内置此类功能?
TypeScript本身没有针对SQL操作场景的内置封装或专属类型,你当前使用的泛型默认值、Parameters工具类型等都是TypeScript的通用类型特性,已经被合理利用。针对SQL操作的类型区分,需要开发者根据业务场景自行封装。
内容的提问来源于stack exchange,提问作者Casper Kuethe
相关产品推荐
相关产品推荐

