这篇文章将介绍unknown 类型,以及如何将其用于类型安全的数据获取:

any 类型的复习
当我们不确定值的类型时,可以使用any 类型。any 的问题是,对于any 类型的值,不会进行类型检查。
如果有一种类型像any ,可以用于我们不知道的值,但也是类型安全的呢?这就是unknown 类型!
了解unknown 类型
考虑一下下面的函数:
function add(a: unknown, b: unknown) {
return a + b; // 💥 Object is of type 'unknown'
}
该代码包含一个将参数值相加并返回结果的函数。参数的类型是unknown 。
在引用a 和b 的地方会发生类型错误,因为unknown 类型的变量不能加在一起。
所以,类型检查确实发生在unknown 类型上,与any 类型不同。
如果我们更新该函数,使其具有下面的实现,类型错误就会消失:
function add(a: unknown, b: unknown) {
if ( typeof a === "number" && typeof b === "number" ) { return a + b;
} return 0;}
第2行的if 语句被称为类型保护。类型保护允许TypeScript将a 和b 的类型从unknown 调整到number 。然后,if 语句中的代码可以对a 和b 进行操作。
你不能直接对类型为
unknown的变量进行操作。我们必须给TypeScript提供信息来缩小类型,以便可以使用。
类型安全的数据获取
现在我们了解了unknown 类型,让我们以强类型的方式使用它来获取数据。考虑一下下面的代码:
async function getData(
path: string
): Promise<unknown> {
const response = await fetch(path);
return await response.json();
}
这是一个调用网络API并返回响应体中数据的实用函数。从该函数返回的数据被赋予了unknown 类型。
让我们使用这个函数从一个网络API中获取一个人:
type Person = {
id: string;
name: string;
};
async function getPerson(
id: string
): Promise<Person | null> {
const person = await getData("/people/1");
return person; // 💥 Type 'unknown' is not assignable to type 'Person | null'.}
在突出显示的一行中发生了类型错误,在这一行中,person 变量被从getPerson 函数中返回。这是因为person 的类型是unknown ,它与Person 或null 不兼容。
我们需要检查person 实际上是Person 类型,以解决类型错误。我们可以使用所谓的类型谓词来做这件事:
function isPerson(
person: any
): person is Person {
return "id" in person && "name" in person;
}
注意返回类型,person is Person 。这是一个类型谓词;它是一个特殊的返回类型,Typescript编译器用它来知道一个特定的值是什么类型。
让我们使用isPerson 类型来缩小person 从unknown 到Person :
async function getPerson(
id: string
): Promise<Person | null> {
const person = await getData("/people/1");
if (person && isPerson(person)) { return person; // type is narrowed to `Person`
}
return null;
}
正如我们所期望的那样,类型错误消失了。
很好!
总结
unknown 类型允许我们减少对any 的使用并创建更多强类型的代码。当使用unknown 时,我们会写更多的代码,但是我们从知道我们的代码是类型安全的中得到的信心是非常值得的。