摘要:在本教程中,您将学习 TypeScript 未知类型,以强制执行未知值的类型检查。
TypeScript 未知类型的介绍
在 TypeScript 中,unknown 类型可以保存一个预先未知但需要类型检查的值。
要声明一个 unknown 类型的变量,您可以使用以下语法
let result: unknown;Code language: TypeScript (typescript)与 any 类型 一样,您可以将任何值分配给 unknown 类型的变量。例如
let result: unknown;
result = 1;
result = 'hello';
result = false;
result = Symbol();
result = { name: 'John' };
result = [1, 2, 3];Code language: TypeScript (typescript)与 any 类型不同,TypeScript 在对其执行操作之前会检查类型。
例如,您不能在 unknown 值上调用方法或应用运算符。如果尝试这样做,TypeScript 编译器将发出错误
let result: unknown;
result = [1,2,3];
const total = result.reduce((a: number, b:number ) => a + b, 0);
console.log(total);Code language: TypeScript (typescript)在此示例中,result 变量的类型为 unknown。我们将一个数组赋值给 result 变量,但其类型仍然为 unknown。因此,我们无法在其上调用数组的 reduce() 方法。
要调用 result 变量上的 reduce() 方法,您需要使用 类型断言 明确告诉 TypeScript 编译器 result 的类型为 数组。例如
let result: unknown;
result = [1, 2, 3];
const total = (result as number[]).reduce((a: number, b: number) => a + b, 0);
console.log(total); // 6Code language: TypeScript (typescript)在此示例中,我们明确告诉 TypeScript 编译器 result 的类型为数字数组 (result as number[])。
因此,我们可以毫无问题地调用 result 数组上的 reduce() 方法。
unknown 与 any 类型
下表重点介绍了 unknown 和 any 类型之间的主要区别
| 特性 | any | unknown |
|---|---|---|
| 类型安全 | 无类型安全 | 强制执行类型安全 |
| 操作 | 可以在没有检查的情况下执行操作 | 在没有类型断言(类型缩小)的情况下无法执行操作 |
| 用例 | 对动态值很有用,但不安全。 | 对动态值很有用且安全,因为它需要在使用前进行验证。 |
| 类型检查 | TypeScript 编译器不会对 any 变量执行类型检查。 | TypeScript 编译器会对 unknown 变量强制执行类型检查。 |
| 常见场景 | 用于将 JavaScript 代码库迁移到 TypeScript。 | 在处理来自外部源(API 调用、数据库等)的数据时使用,在这些数据中需要类型验证。 |
TypeScript 未知类型示例
让我们来看一些使用 Typescript unknown 类型的实用示例。
1) 处理外部数据
在从外部 API 接收数据时,您可以使用 unknown 类型在处理数据之前强制执行验证。
以下示例演示了如何使用 fetch 方法 从 https://jsonplaceholder.typicode.com/posts 端点调用 API
const fetchData = async (url: string): Promise<unknown> => {
const response = await fetch(url);
return await response.json();
};
const showPosts = async () => {
const url = 'https://jsonplaceholder.typicode.com/posts';
try {
const posts = await fetchData(url); // unknown type
(
posts as { userId: number; id: number; title: string; body: string }[]
).map((post) => console.log(post.title));
} catch (err) {
console.log(err);
}
};
showPosts();Code language: TypeScript (typescript)工作原理。
首先,定义一个函数 fetchData,它从 URL 调用 API 并返回 JSON 数据。由于返回数据的形状未知,因此函数返回一个 Promise<unknown> 值
const fetchData = async (url: string): Promise<unknown> => {
const response = await fetch(url);
return await response.json();
};Code language: TypeScript (typescript)其次,定义 showPosts() 函数,它使用 fetchData() 函数从 https://jsonplaceholder.typicode.com/posts 端点调用 API
const showPosts = async () => {
const url = 'https://jsonplaceholder.typicode.com/posts';
try {
const posts = await fetchData(url); // unknown type
(
posts as { userId: number; id: number; title: string; body: string }[]
).map((post) => console.log(post.title));
} catch (err) {
console.log(err);
}
};Code language: TypeScript (typescript)在此示例中,posts 变量的类型为 unknown。
在访问其 title 属性之前,我们使用 类型断言 指示 TypeScript 编译器将其视为帖子对象的数组
posts as { userId: number; id: number; title: string; body: string }[]Code language: TypeScript (typescript)第三,调用 showPosts() 函数
showPosts();Code language: TypeScript (typescript)2) 创建类型安全的接口
以下示例定义了一个函数 format,它在将值记录到控制台之前对其进行格式化
function format(value: unknown): void {
switch (typeof value) {
case 'string':
console.log('String:', value.toUpperCase());
break;
case 'number':
console.log('Number:', value.toFixed(2));
break;
default:
console.log('Other types:', value);
}
}Code language: TypeScript (typescript)在此示例中,在访问值的某个方法之前,我们验证其类型以确保操作有效。
总结
unknown类型类似于 any 类型,但更严格。- 使用
unknown类型来处理来自外部源的数据,并在使用前需要验证。