TypeScript如何避免DynamoDB扫描与查询的代码重复?
解决DynamoDB Scan/Query代码重复的问题
你遇到的报错核心原因是:ScanInput和QueryInput是TypeScript的接口,不是JavaScript运行时存在的类。接口只在编译阶段生效,运行时会被完全擦除,所以既没法用instanceof判断类型,也不能通过DynamoDB.DocumentClient.ScanInput访问到它们(这就是你看到Property 'ScanInput' does not exist报错的原因)。
下面是几种实用的代码去重方案:
方案1:传入操作类型,通用函数复用逻辑
这是最简洁的方式,直接把要调用的方法名(scan/query)作为参数传给通用函数,无需类型判断:
private static async queryOrScan<T extends DynamoDB.DocumentClient.QueryInput | DynamoDB.DocumentClient.ScanInput>( operation: 'query' | 'scan', params: T ): Promise<any[]> { let items; const results: any[] = []; do { items = await this.getDbClient()[operation](params).promise(); (items.Items || []).forEach(item => results.push(item)); params.ExclusiveStartKey = items.LastEvaluatedKey; } while (typeof items.LastEvaluatedKey !== 'undefined'); return results; } // 原有方法简化为调用通用函数 static scanTable = async (params: DynamoDB.DocumentClient.ScanInput) => { return this.queryOrScan('scan', params); } static queryTable = async (params: DynamoDB.DocumentClient.QueryInput) => { return this.queryOrScan('query', params); }
方案2:自定义类型守卫区分参数
如果不想额外传操作名,可以利用两种输入参数的属性差异写类型守卫:QueryInput必然包含KeyConditionExpression,而ScanInput没有这个属性(全表扫描场景)。
// 自定义类型守卫,编译期校验参数类型 function isQueryInput(params: any): params is DynamoDB.DocumentClient.QueryInput { return 'KeyConditionExpression' in params; } private static async fetchItems( params: DynamoDB.DocumentClient.QueryInput | DynamoDB.DocumentClient.ScanInput ): Promise<any[]> { let items; const results: any[] = []; do { // 根据类型守卫判断调用对应方法 items = isQueryInput(params) ? await this.getDbClient().query(params).promise() : await this.getDbClient().scan(params).promise(); (items.Items || []).forEach(item => results.push(item)); params.ExclusiveStartKey = items.LastEvaluatedKey; } while (typeof items.LastEvaluatedKey !== 'undefined'); return results; } // 简化原有方法 static scanTable = async (params: DynamoDB.DocumentClient.ScanInput) => { return this.fetchItems(params); } static queryTable = async (params: DynamoDB.DocumentClient.QueryInput) => { return this.fetchItems(params); }
方案3:泛型+函数重载强化类型安全
如果需要更严格的类型约束,确保操作和参数类型一一对应,可以用函数重载+泛型实现:
// 函数重载:明确不同参数对应的函数签名 private static async fetchItems(params: DynamoDB.DocumentClient.QueryInput): Promise<any[]>; private static async fetchItems(params: DynamoDB.DocumentClient.ScanInput): Promise<any[]>; // 核心实现逻辑 private static async fetchItems( params: DynamoDB.DocumentClient.QueryInput | DynamoDB.DocumentClient.ScanInput ): Promise<any[]> { let items; const results: any[] = []; do { // 直接用属性判断替代类型守卫 const operation = 'KeyConditionExpression' in params ? 'query' : 'scan'; items = await this.getDbClient()[operation](params).promise(); (items.Items || []).forEach(item => results.push(item)); params.ExclusiveStartKey = items.LastEvaluatedKey; } while (typeof items.LastEvaluatedKey !== 'undefined'); return results; } // 原有方法简化 static scanTable = async (params: DynamoDB.DocumentClient.ScanInput) => { return this.fetchItems(params); } static queryTable = async (params: DynamoDB.DocumentClient.QueryInput) => { return this.fetchItems(params); }
内容的提问来源于stack exchange,提问作者asdasf
相关产品推荐
相关产品推荐

