《TypeScript全面指南》第三章:any 类型,unknown 类型,never 类型

148 阅读4分钟

any 类型

基本含义

any 类型是 TypeScript 的一种超集类型,表示可以是任何值。使用 any 类型可以让您在编译时绕过类型检查,从而可以在 TypeScript 中以 JavaScript 的自由方式编写代码。

let anything: any = "hello";
anything = 42;
anything = [1, 2, 3];

类型推断问题

使用 any 类型会使 TypeScript 丧失关于该值的类型信息,这意味着您无法获得编译时的类型检查或者编辑器的智能提示。

污染问题

由于 any 类型可以赋给任何类型,它容易“污染”其它的类型。例如,如果函数的参数是 any 类型,那么无论您传递什么类型的值,TypeScript 都不会产生错误。

unknown 类型

any 类型类似,unknown 类型表示任何值的类型。但不同之处在于,当你试图将 unknown 类型的值分配给其他类型的变量或将其作为函数的参数时,TypeScript 会进行类型检查。

let unknownValue: unknown;
unknownValue = "hello";
unknownValue = 42;

// Error: Type 'unknown' is not assignable to type 'string'.
let myString: string = unknownValue;

为了安全地使用 unknown 类型的值,您需要进行某种形式的类型断言类型检查

if (typeof unknownValue === "string") {
    let myString: string = unknownValue;  // 这是安全的
}

或者使用类型断言:

let myString: string = unknownValue as string;

never 类型

never 类型表示永远不可能有值的类型。例如,一个函数如果永远抛出错误且不返回任何值,那么它的返回类型是 never

function throwError(message: string): never {
    throw new Error(message);
}

never 类型常用于确保某些代码路径永远不会被执行。与此相反,如果一个函数有 return 语句,那么它的返回类型不能是 never

注意: never 类型也可以用来表示永远不可能存在的值的类型,例如在条件类型或类型映射中。

总结

  • any 类型提供了完全的灵活性,但牺牲了类型安全性
  • **unknown 类型是 any 类型的类型安全版本**,它要求你在操作值之前进行类型检查。
  • never 类型表示永远不会有值的类型,它通常用于错误处理或表示不可能的代码路径。

思考

TypeScript 类型挑战

考虑以下 TypeScript 函数:

function processData(input: any | unknown) {

    // 任务 1: 在这里,不使用类型断言或类型检查,
    // 尝试将 input 赋值给一个明确声明为 string 类型的变量。
    let task1: string;
    // your code for task 1 here...

    // 任务 2: 使用类型检查,确保 input 是一个数字,
    // 然后将其赋值给一个明确声明为 number 类型的变量。
    let task2: number;
    // your code for task 2 here...

    // 任务 3: 写一个函数,该函数的返回类型为 never,
    // 并在某些条件下调用这个函数。
    function throwError(message: string): never {
        throw new Error(message);
    }

    // your code for task 3 here...
}
  1. 对于任务 1,你会遇到什么问题?如果不能直接赋值,为什么?

对于任务 1,您将无法直接将 input 赋给 task1 变量,因为 input 的类型是 any | unknownany 类型允许赋值,但 unknown 类型不允许这样做,除非经过类型检查或断言。

尝试赋值的代码可能是这样的:

task1 = input;  // 这将引发错误,因为 `unknown` 类型不能直接赋给其他具体类型。

问题回答:

  • 您会遇到一个编译错误,因为 TypeScript 不允许将 unknown 类型的值直接赋给其他具体类型,除非您已经明确地检查了该类型或使用了类型断言。
  1. 对于任务 2,请提供一个使用类型检查确保 input 是数字的方法。

要确保 input 是一个数字并赋值给 task2,您需要进行类型检查:

if (typeof input === "number") {
    task2 = input;
} else {
    console.error("Input is not a number!");
}
  1. 对于任务 3,描述 never 类型的用途并实现条件下调用 throwError 的代码。

never 类型表示那些永远不可能有值的类型。例如,一个函数如果永远抛出错误并且永不返回,那么它的返回类型就是 never

以下是如何在某些条件下调用 throwError 的代码:

if (typeof input !== "number" && typeof input !== "string") {
    throwError("Invalid input type!");  // 如果 input 既不是数字也不是字符串,我们就抛出一个错误。
}

问题回答:

  • never 类型用于表示那些永远不会发生的值。在函数上下文中,一个永远不返回值(例如,因为它内部总是抛出错误)的函数会有 never 的返回类型。在上面的代码中,当 input 既不是数字也不是字符串时,我们调用了 throwError 函数,这会导致函数停止执行并抛出错误。