any类型与unknown类型的主要区别
- 类型检查宽松程度:
- any类型:非常宽松,它允许你对该类型的变量进行任何操作,而不会在编译时引发类型错误。例如:
let anyVar: any = "hello";
anyVar = 123;
anyVar.foo();// 这里不会在编译时报错,即使字符串类型没有foo方法
- unknown类型:更加严格,它不允许对该类型的变量进行任何操作,除非你先进行类型断言或类型缩小。例如:
let unknownVar: unknown = "hello";
// unknownVar.foo(); // 这里会在编译时报错,因为unknown类型不允许直接操作
- 赋值兼容性:
- any类型:可以赋值给任何类型,任何类型也可以赋值给它。例如:
let num: number = 10;
let anyVar: any = num;
let str: string = anyVar; // 不会报错
- unknown类型:只能赋值给unknown类型或any类型,不能直接赋值给其他具体类型。例如:
let unknownVar: unknown = "hello";
let str: string;
// str = unknownVar; // 会报错,不能直接将unknown类型赋值给string类型
优先选择unknown类型的场景及原因
- 从外部来源接收数据时:
- 场景:比如从
fetch
API获取的数据,或者从用户输入获取的数据。例如:
async function fetchData() {
const response = await fetch('https://example.com/api/data');
const data: unknown = await response.json();
if (Array.isArray(data) && data.every(item => typeof item === 'number')) {
const numbers: number[] = data as number[];
// 可以安全地对numbers进行数组操作
}
}
- 原因:使用unknown类型可以确保在处理外部数据时,不会在未进行类型检查的情况下就对数据进行操作,从而避免潜在的运行时错误。如果使用any类型,可能会在数据结构不符合预期时,在运行时抛出错误,而使用unknown类型能在编译时就发现潜在问题。
- 定义函数参数,参数类型不确定时:
- 场景:编写一个通用的日志记录函数,它可以接受任何类型的参数进行记录。例如:
function logData(data: unknown) {
if (typeof data ==='string') {
console.log(`String: ${data}`);
} else if (typeof data === 'number') {
console.log(`Number: ${data}`);
} else {
console.log('Other type');
}
}
logData('hello');
logData(123);
logData({});
- 原因:使用unknown类型能明确告知调用者和代码阅读者,这个参数类型是不确定的,必须在函数内部进行类型检查后才能安全操作。而any类型会隐藏这种不确定性,可能导致调用者在不了解参数实际类型的情况下进行错误的操作。