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

如何重构触发Sonar告警的getBodyFields TypeScript函数

Sonar告警原因

原函数触发Sonar重构规则的核心问题是违反了DRY(Don't Repeat Yourself)原则:

  • 17个可选字段全部重复编写「值存在且不是空字符串」的判断逻辑,代码冗余度超过70%
  • 后续新增、删除需要透传的字段时,需要重复编写结构完全一致的代码,容易出现拼写错误、漏判问题
  • 现有判空逻辑存在缺陷:当字段值为0、false这类业务上合法的假值时,会被错误过滤,不会被带到请求体中
可选重构方案

方案1:字段统一遍历(首推,平衡可维护性和安全性)

将所有需要过滤空值的字段统一维护在常量列表中,通过循环统一做判空处理,既消除重复代码,又能精确控制需要透传的字段,不会把request上多余的属性带到请求体:

function getBodyFields(request: UpdateCustomerRequest, tmsGuid: string) {
  // 所有需要透传、且需要过滤空值的字段统一在这里维护
  const validFields = [
    'organizationName', 'firstName', 'middleInitial', 'lastName',
    'email', 'communicationEmail', 'areaCode', 'phoneNumber',
    'phoneType', 'alternatePhoneAreaCode', 'alternatePhoneNumber',
    'alternatePhoneType', 'address1', 'address2', 'city', 'state', 'zip'
  ] as const;

  const body: Record<string, unknown> = { tmsGuid };
  for (const field of validFields) {
    const fieldValue = request[field];
    // 仅过滤null、undefined、空字符串,保留0、false等合法值
    if (fieldValue != null && fieldValue !== "") {
      body[field] = fieldValue;
    }
  }

  return body as { tmsGuid: string } & Partial<Pick<UpdateCustomerRequest, typeof validFields[number]>>;
}

这个方案的优势:

  • 重复代码完全消除,后续调整透传字段只需要修改validFields数组即可
  • 判空逻辑更严谨,修复原代码误过滤合法假值的问题
  • TypeScript类型安全,字段拼写错误会被TS直接提示

方案2:通用工具函数抽离(适合多场景复用)

如果项目中多处需要做对象空值过滤,可以把过滤逻辑抽成通用工具函数,减少全项目的重复代码:

/**
 * 过滤对象中值为null、undefined、空字符串的属性
 * 注意:会遍历对象所有自有属性,仅适用于对象属性和接口字段完全对应的场景
 */
function filterEmptyProps<T extends Record<string, any>>(source: T): Partial<T> {
  return Object.fromEntries(
    Object.entries(source).filter(([_, val]) => val != null && val !== "")
  ) as Partial<T>;
}

function getBodyFields(request: UpdateCustomerRequest, tmsGuid: string) {
  return {
    tmsGuid,
    ...filterEmptyProps(request)
  };
}

注意:如果UpdateCustomerRequest类型中存在不需要透传给接口的字段,不要使用这个方案,避免多余字段被带到请求体中引发接口报错。

方案3:最小改动方案(不调整原有代码结构)

如果不想调整原有代码的展开写法,只需要把重复的判空逻辑抽成公共判断函数,即可消除Sonar的重复代码告警:

function getBodyFields(request: UpdateCustomerRequest, tmsGuid: string) {
  // 抽离重复的非空判断逻辑
  const isNonEmpty = <T>(val: T): val is NonNullable<T> => val != null && val !== "";

  return {
    tmsGuid,
    ...(isNonEmpty(request.organizationName) && { organizationName: request.organizationName }),
    ...(isNonEmpty(request.firstName) && { firstName: request.firstName }),
    ...(isNonEmpty(request.middleInitial) && { middleInitial: request.middleInitial }),
    ...(isNonEmpty(request.lastName) && { lastName: request.lastName }),
    ...(isNonEmpty(request.email) && { email: request.email }),
    ...(isNonEmpty(request.communicationEmail) && { communicationEmail: request.communicationEmail }),
    ...(isNonEmpty(request.areaCode) && { areaCode: request.areaCode }),
    ...(isNonEmpty(request.phoneNumber) && { phoneNumber: request.phoneNumber }),
    ...(isNonEmpty(request.phoneType) && { phoneType: request.phoneType }),
    ...(isNonEmpty(request.alternatePhoneAreaCode) && { alternatePhoneAreaCode: request.alternatePhoneAreaCode }),
    ...(isNonEmpty(request.alternatePhoneNumber) && { alternatePhoneNumber: request.alternatePhoneNumber }),
    ...(isNonEmpty(request.alternatePhoneType) && { alternatePhoneType: request.alternatePhoneType }),
    ...(isNonEmpty(request.address1) && { address1: request.address1 }),
    ...(isNonEmpty(request.address2) && { address2: request.address2 }),
    ...(isNonEmpty(request.city) && { city: request.city }),
    ...(isNonEmpty(request.state) && { state: request.state }),
    ...(isNonEmpty(request.zip) && { zip: request.zip }),
  }
}

内容的提问来源于stack exchange,提问作者sagar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 03:12:14