1. 使用 unknown
提升代码健壮性、可维护性和类型安全性
- 何时使用
unknown
:当你不确定一个值的类型时,unknown
是比 any
更安全的选择。例如,从 JSON.parse
得到的值,因为 JSON 可以表示多种类型(字符串、数字、布尔、对象、数组等),此时就适合用 unknown
。
let jsonResult: unknown;
try {
jsonResult = JSON.parse('{ "name": "John" }');
} catch (error) {
console.error('Error parsing JSON:', error);
}
- 如何处理
unknown
:在对 unknown
类型的值进行操作前,必须先进行类型缩小。可以使用类型断言、typeof
检查、instanceof
检查等方式。
if (typeof jsonResult === 'object' && jsonResult!== null) {
const obj = jsonResult as { name: string };
console.log(obj.name);
}
- 优势:使用
unknown
可以避免在不明确类型的情况下意外调用不存在的方法或属性,从而提升代码的健壮性和类型安全性。同时,明确的类型缩小过程也提高了代码的可维护性,因为后续开发者能清晰看到类型检查的逻辑。
2. 使用 never
提升代码健壮性、可维护性和类型安全性
- 何时使用
never
:never
类型表示永远不会出现的值。比如在一个函数中,抛出异常或进入死循环,该函数就不会有返回值,其返回类型就是 never
。
function throwError(message: string): never {
throw new Error(message);
}
- 如何处理
never
:在条件类型或类型守卫中,可以利用 never
来处理不可能的情况。例如,在一个联合类型的 switch
语句中,当所有情况都被处理完后,default
分支的类型应该是 never
。
type Animal = 'dog' | 'cat';
function handleAnimal(animal: Animal) {
switch (animal) {
case 'dog':
console.log('It\'s a dog');
break;
case 'cat':
console.log('It\'s a cat');
break;
default:
const _exhaustiveCheck: never = animal;
console.log(_exhaustiveCheck); // 此处不会执行,若有未处理的情况会报错
}
}
- 优势:使用
never
可以确保代码逻辑的完整性,避免遗漏对某些情况的处理,提升代码的健壮性和类型安全性。同时,也提高了代码的可维护性,因为明确了哪些情况是不应该出现的。
3. 使用 unknown
和 never
可能遇到的挑战及解决方案
unknown
类型缩小不严谨
- 挑战:在进行类型缩小时,如果条件判断不严谨,可能会导致类型断言错误,从而引发运行时错误。例如,错误地假设
unknown
类型的值是一个对象,并进行属性访问。
- 解决方案:在进行类型缩小时,尽可能使用多种类型检查方式,确保类型的准确性。同时,在类型断言时,添加必要的防御性代码,如
if (obj && 'property' in obj)
来避免访问不存在的属性。
never
类型未正确处理
- 挑战:在
switch
语句等场景中,如果没有正确处理 never
类型,可能会遗漏一些意外情况,导致程序在运行时出现未预料的行为。
- 解决方案:在处理联合类型等可能出现
never
类型的场景时,始终添加 default
分支,并将其类型标记为 never
。这样,一旦有未处理的情况,TypeScript 编译器会报错,提醒开发者进行处理。在实际项目中,这种严谨的处理方式有助于及时发现潜在的逻辑漏洞。例如,在处理不同类型的用户输入时,确保所有可能的输入类型都被正确处理,避免出现未处理的分支导致程序异常。