掌握 TypeScript 的边界:any, unknown, void, never 的正确用法与陷阱

一、 void

void 是我们最常遇到的特殊类型,也是最容易理解的。它表示没有任何返回值

typescript 复制代码
// 这个函数只是打印日志,它不返回任何东西。
function logMessage(message: string): void {
    console.log(message);
    return; // 这个return可有可无,代表什么都不返回
}

let v = void 1; // 此情况比较特殊,代表定义了一个`undefined`变量

解析

  • void: 函数返回使用时代表不返回任何值,变量赋值值,沿袭JavaScript用法,定义了一个undefined变量

二、any

any 是TypeScript中的一把"双刃剑"。它代表任何类型,你可以随意修改他。TypeScript会完全放弃对这个变量的任何类型检查。

typescript 复制代码
let anything: any = "hello";

// 你可以对 a 随意赋值,操作等,在编译期间都不会报错,只有在运行时才会报错
anything = 123;                 // OK
anything = { a: 1 };            // OK
anything.run();                 // OK 
anything.toFixed(2);            // OK 

三、unknown

unknown 也代表任何类型 ,但它是一个类型安全的"任何类型"。

它和 any 的核心区别在于:

  • any 类型的变量,可以被任意操作。
  • unknown 类型的变量,在没有被明确断言或类型收窄 之前,不能进行任何操作
typescript 复制代码
let mystery: unknown = "hello";

// 直接操作会报错!TypeScript 会拦住你。
mystery.toUpperCase(); // Error: mystery类型为未知

// 你必须先证明它的类型
if (typeof mystery === "string") {
    // 在这个代码块里,TypeScript 知道 mystery 是 string 类型
    console.log(mystery.toUpperCase()); // OK!
}

// 另一个关键点:unknown 只能赋值给 any 或 unknown
let str: string = mystery; // Error: 不能将类型"unknown"分配给类型"string"
let anything: any = mystery; // OK

四、never

never 是最特殊的类型。它表示永不存在的值的类型 。和void有点相像,但又有区别。

4.1 抛出错误的函数

一个函数如果总是抛出异常,那么它就永远不会正常返回一个值。它的返回类型就是 never

typescript 复制代码
function throwError(message: string): never {
    throw new Error(message);
}

4.2 无限循环的函数

一个永远不会结束的函数,其返回类型也是 never

typescript 复制代码
function infiniteLoop(): never {
    while (true) {
        // ...
    }
}

4.3 用于类型穷尽检查(Exhaustive Checks)

这是 never 最强大、最实用的场景。在 switchif/else 语句中,我们可以利用 never 来确保我们处理了所有可能的情况。

typescript 复制代码
type Shape = 'circle' | 'square' | 'triangle';

function getArea(shape: Shape): number {
    switch (shape) {
        case 'circle':
            return Math.PI;
        case 'square':
            return 1;
        // case "triangle": return 0.5; // <-- 故意注释掉
        default:
            // 如果我们处理了所有 Shape 的情况,`exhaustiveCheck` 理论上永远不会被执行
            const exhaustiveCheck: never = shape;
            // 如果我们漏掉了 'triangle','shape' 的类型在这里是 'triangle'
            // 将 'triangle' 赋值给 'never' 会导致编译时错误!
            //这就提醒我们必须处理 'triangle' case。
            return exhaustiveCheck;
    }
}

4.4 类型注解

typescript 复制代码
let foo: never; // ok

let foo: never = 123; // Error: number 类型不能赋值给 never 类型

// ok, 作为函数返回类型的 never
let bar: never = (() => {
  throw new Error('Throw my hands in the air like I just dont care');
})();
  • never 类型仅能被赋值给另外一个 never

总结

如果你喜欢本教程,记得点赞+收藏!关注我获取更多JavaScript/TypeScript开发干货

相关推荐
Stringzhua5 分钟前
Vue数据的变更操作与表单数据的收集【6】
前端·javascript·vue.js
万少15 分钟前
可可图片编辑 HarmonyOS 上架应用分享
前端·harmonyos
你的人类朋友38 分钟前
git常见操作整理(持续更新)
前端·git·后端
无羡仙38 分钟前
Webpack 核心实战:从零搭建支持热更新与 Babel 转译的现代前端环境
前端·webpack·前端框架
乐~~~1 小时前
el-date-picker type=daterange 日期范围限制
javascript·vue.js·elementui
你的人类朋友1 小时前
git中的Fast-Forward是什么?
前端·git·后端
初遇你时动了情1 小时前
uniapp vue3 ts自定义底部 tabbar菜单
前端·javascript·uni-app
JarvanMo1 小时前
天塌了?Flutter工程总监跑去苹果了?
前端
Jerry3 小时前
迁移到 Jetpack Compose
前端