You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 13:35:15