文章

代码风格指南:优先处理 Default、空值、异常值(开始主逻辑之前,先处理所有可能出错的情况)

代码风格指南:优先处理 Default、空值、异常值(开始主逻辑之前,先处理所有可能出错的情况)

在日常开发中,代码的可读性和健壮性往往来自于对默认值、空值、异常值的优先处理。本文介绍一种在 TypeScript 项目中推荐遵循的代码风格习惯:先处理边界,再处理主干逻辑。

为什么要优先处理 default / 空值 / 异常值?

  • ✅ 提高可读性:开发者可以一眼看到函数的边界处理和默认分支。- ✅ 减少嵌套:避免“层层 if/else”结构。- ✅ 提升健壮性:在进入核心逻辑前,先过滤掉不符合预期的值。- ✅ 易于测试:异常分支逻辑更加清晰、独立。

    函数中优先 return 空值/异常值

反例的写法:

1
2
3
4
5
6
7
8
9
function calculateDiscount(price?: number): number {
  if (price != null) {
    if (price > 100) {
      return price * 0.9;
    }
    return price;
  }
  return 0;
}

推荐写法:

1
2
3
4
5
function calculateDiscount(price?: number): number {
  if (isNil(price)) return 0;
  if (price > 100) return price * 0.9;
  return price;
}

switch 结构中把 default 放在最前面

反例的写法:

1
2
3
4
5
6
7
8
switch (status) {
  case 'success':
    return handleSuccess();
  case 'fail':
    return handleFail();
  default:
    return handleUnknown();
}

推荐写法:

1
2
3
4
5
6
7
8
switch (status) {
  default:
    return handleUnknown();
  case 'success':
    return handleSuccess();
  case 'fail':
    return handleFail();
}

正则表达式前先判断空值

1
2
3
4
function matchPhone(input?: string): boolean {
  if (isNil(input)) return false;
  return /^1\d{10}$/.test(input);
}

表单校验中优先判断空值并 return

1
2
3
4
5
const validator = (_: any, value: string) => {
  if (isNil(value)) return Promise.reject('不能为空');
  if (!/^\d+$/.test(value)) return Promise.reject('只能是数字');
  return Promise.resolve();
};

三元运算符中优先判断空值

推荐写法:

1
const display = isNil(value) ? '-' : value;

Vue 模板中:

1
{{ isNil(price) ? '-' : priceFormat(price) }}

接口数据处理默认值

1
2
const productName = isNil(data.productName) ? '未知商品' : data.productName;
const stock = isNil(data.stock) ? 0 : data.stock;

封装为函数:

1
2
3
function safeValue<T>(value: T | null | undefined, fallback: T): T {
  return isNil(value) ? fallback : value;
}

数组操作前判断空值

1
return isNil(list) ? [] : list.map(item => item.name);

可选链:

1
return list?.map(item => item.name) ?? [];

表单初始值处理

1
2
3
4
const formModel = reactive({
  amount: props.amount ?? 0,
  type: props.type ?? 'default',
});

对象解构时设置默认值

1
2
3
4
5
const {
  page = 1,
  pageSize = 10,
  keyword = '',
} = props.options ?? {};

computed 中优先判断非法值

1
2
3
const formattedAmount = computed(() =>
  isNil(data.amount) || isNaN(data.amount) ? '-' : priceFormat(data.amount)
);

事件处理函数中优先判断边界值

1
2
3
4
5
6
7
8
9
10
11
function onSubmit(formData: FormData) {
  if (isNil(formData)) {
    console.warn('无效的表单数据');
    return;
  }
  if (!formData.name) {
    message.error('请输入名称');
    return;
  }
  // 正常处理逻辑...
}

Vue 组件中 props 防御性处理

1
2
3
4
5
6
7
8
defineProps<{
  show: boolean;
  count?: number;
}>();

const safeCount = computed(() => {
  return isNil(props.count) ? 0 : props.count;
});

接口调用前预校验参数合法性

1
2
3
4
5
6
7
8
async function fetchUser(id?: string) {
  if (isNil(id) || id.trim() === '') {
    console.error('用户 ID 不能为空');
    return;
  }
  const res = await api.get(`/user/${id}`);
  return res.data;
}

小结:常见场景推荐方式

| 场景 | 推荐做法 || — | — || 接口字段处理 | isNil 判断,设定默认值 || 三元表达式展示 | isNil(value) ? fallback : value || 解构参数 | 使用 ?? 设置默认值 || 数组操作前判断 | isNil(array) ? [] : array.map(…) || computed 中 | computed(() => isNil(val) ? fallback : format(val)) || 表单/事件校验 | 先 if (isNil(x)) return 再逻辑 || 组件 prop 默认值 | prop.value ?? fallback |

请记住这条原则:在开始主逻辑之前,先处理所有可能出错的情况。 这不仅是一个风格建议,更是一种让你写出更安全、稳定、好维护代码的方式。

本文由作者按照 CC BY 4.0 进行授权