如何消除TypeScript中DynamoDB扫描与查询代码的重复?
解决DynamoDB Scan/Query方法的代码重复问题
你遇到的错误核心原因是:DynamoDB.DocumentClient.ScanInput 和 QueryInput 是TypeScript接口,仅存在于编译阶段,运行时没有对应的类构造函数,所以用instanceof判断类型完全无效;同时DocumentClient的静态属性里也不包含这两个类型的定义,因此会抛出属性不存在的错误。
下面提供两种可行的代码复用方案:
方案一:通过操作类型标识统一处理
把重复的初始化、错误处理、结果解析逻辑抽进通用方法,通过传入'scan'或'query'标识要执行的操作:
import { DynamoDB } from 'aws-sdk'; // 定义联合类型覆盖两种输入参数 type DBRequestParams = DynamoDB.DocumentClient.ScanInput | DynamoDB.DocumentClient.QueryInput; // 限定允许的操作类型 type DBOperationType = 'scan' | 'query'; class DBService { // 通用核心方法 private static async handleTableOperation(operation: DBOperationType, params: DBRequestParams) { const client = new DynamoDB.DocumentClient(); try { // 类型断言确保操作方法存在并匹配参数类型 const result = await (client[operation] as (params: DBRequestParams) => { promise: () => Promise<any> })(params).promise(); // 统一结果处理逻辑 return result.Items ?? []; } catch (err) { // 统一错误包装 const opName = operation.charAt(0).toUpperCase() + operation.slice(1); throw new Error(`${opName} failed: ${(err as Error).message}`); } } // 对外暴露的Scan方法 static async scanTable(params: DynamoDB.DocumentClient.ScanInput) { return this.handleTableOperation('scan', params); } // 对外暴露的Query方法 static async queryTable(params: DynamoDB.DocumentClient.QueryInput) { return this.handleTableOperation('query', params); } }
方案二:传入操作函数实现强类型安全
如果想要更严格的类型校验,可以直接传入client.scan或client.query作为操作函数,利用TypeScript的泛型自动推断参数和返回值类型:
import { DynamoDB } from 'aws-sdk'; class DBService { // 通用执行函数,泛型约束参数和操作类型匹配 private static async executeDBOperation< T extends DynamoDB.DocumentClient.ScanInput | DynamoDB.DocumentClient.QueryInput, O extends DynamoDB.DocumentClient.ScanOutput | DynamoDB.DocumentClient.QueryOutput >( operation: (params: T) => { promise: () => Promise<O> }, params: T ) { const client = new DynamoDB.DocumentClient(); try { // 通过call绑定client上下文,确保操作方法能正确执行 const result = await operation.call(client, params).promise(); return result.Items ?? []; } catch (err) { // 从操作函数名称生成错误提示 const opName = operation.name.charAt(0).toUpperCase() + operation.name.slice(1); throw new Error(`${opName} failed: ${(err as Error).message}`); } } static async scanTable(params: DynamoDB.DocumentClient.ScanInput) { return this.executeDBOperation(client => client.scan, params); } static async queryTable(params: DynamoDB.DocumentClient.QueryInput) { return this.executeDBOperation(client => client.query, params); } }
这两种方案都能彻底消除代码重复,同时避免你之前遇到的TypeScript类型错误。方案二更强调类型安全,方案一更简洁直观,可根据你的实际需求选择。
内容的提问来源于stack exchange,提问作者asdasf
相关产品推荐
相关产品推荐

