在日常开发中,代码的可读性和健壮性往往来自于对默认值、空值、异常值的优先处理。本文介绍一种在 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 |
请记住这条原则:在开始主逻辑之前,先处理所有可能出错的情况。 这不仅是一个风格建议,更是一种让你写出更安全、稳定、好维护代码的方式。