别在傻傻分不清any void never unknown的场景啦

前言

  • 常网IT源码上线啦!
  • 本篇录入技术选型专栏,希望能祝君拿下Offer一臂之力,各位看官感兴趣可移步🚶。
  • 有人说面试造火箭,进去拧螺丝;其实个人觉得问的问题是项目中涉及的点 || 热门的技术栈都是很好的面试体验,不要是旁门左道冷门的知识,实际上并不会用到的。
  • 接下来想分享一些自己在项目中遇到的技术选型以及问题场景。

代码敲着敲着便有点感悟。

人生的路,没有标准答案,也没有永远正确的导航系统。我们唯一能做的,就是像一个优秀的程序员对待自己编写的代码一样,不断去认识自己,了解自己的优点和缺点,知道自己内心深处真正想要什么,又在恐惧什么。然后,根据这些认知,去调整自己的行为模式,优化自己的"人生算法"。

一、前言

TypeScript相信已经挺成熟了,再众多项目中都用上了,虽然工作量是增大了,但总体利大于弊。

还是得学。

得用。

直入正文。

any void never unknown 有什么区别?

以及在什么场景上用哪个,这篇一定给各位讲懂。

二、any void never unknown

主要区别:

  • any 任意类型(不进行类型检查)

  • void 没有任何类型,和 any 相反

  • never 永不存在的值的类型

  • unknown 未知类型(一个更安全的 any)

代码示例:

java 复制代码
function fn(): void {} // void 一般定义函数返回值

// 返回 never 的函数,必须存在无法达到的终点
function error(msg: string): never {
  throw new Error(msg)
}

function infiniteLoop(): never {
  while (true) {}
}

const car: any = 'baoma'
console.log(car.toUpperCase()) // 不会报错,但不安全

// unknown 比直接使用 any 更安全
const bicycle: unknown = '单车'
// console.log( bicycle.toUpperCase() ) // 会报错!!!
console.log((bicycle as string).toUpperCase()) // 使用 as 转换类型,意思是告诉 TS 编译器:"我知道 bicycle 的类型,我对安全负责"

接着主要讲一下neverunknown,这两个的场景稍微比较难理解。

三、never

表示永远不会出现的值类型。

java 复制代码
// 1. 不可能返回的函數
function error(message: string): never {
    throw new Error(message);
}

// 2. 无限循环
function infiniteLoop(): never {
    while(true) {}
}

// 3. 类型收窄终极判断
type All = string | number
function check(type: All) {
    if (typeof type === "string") {
        // 这里 type 是 string
    } else if (typeof type === "number") {
        // 这里 type 是 number
    } else {
        // 这里 type 是 never
        const unreachable: never = type
    }
}

进阶应用场景:

  1. 排除联合类型中的特定类型
java 复制代码
type T = Exclude<string | number | boolean, number> // string | boolean
  1. 空对象过滤(工具类型实现)
java 复制代码
type NonNullable<T> = T extends null | undefined ? never : T
// 作用:过滤类型中的 null 和 undefined

// 应用:
type T1 = string | null | undefined
type CleanT1 = NonNullable<T1> // 最终类型变成 string

type T2 = number[] | undefined
type CleanT2 = NonNullable<T2> // 最终类型变成 number[]
  1. 类型映射过滤(删除属性)
java 复制代码
type RemoveKindField<T> = {
    [K in keyof T as Exclude<K, "kind">]: T[K]
}

// 作用:移除对象类型中的 kind 属性
interface Device {
    kind: string;
    id: number;
    name: string;
}

type CleanDevice = RemoveKindField<Device>
/* 结果类型:
{
    id: number;
    name: string;
}
*/
  1. 联合类型完整性检查
java 复制代码
type Animal = "cat" | "dog"
function handleAnimal(animal: Animal) {
    switch(animal) {
        case "cat": break
        case "dog": break
        default: 
            const _exhaustiveCheck: never = animal // 如果 Animal 新增类型会报错
    }
}

在业务代码中的实际应用:

java 复制代码
// 类型安全的对象属性访问
function getSafeValue<T, K extends keyof T>(obj: T, key: K): T[K] | never {
    if (!(key in obj)) {
        throw new Error(`属性 ${String(key)} 不存在`)
    }
    return obj[key]
}

// 应用在你的 fillLevel 对象
const level = getSafeValue(fillLevel, 2)  // 正确:"省级"
const invalid = getSafeValue(fillLevel, 7) // 编译时报错 + 运行时报错

讲了这么多,其实never 类型的主要作用是:

  1. 增强类型安全性,确保代码覆盖所有可能情况

  2. 在类型系统中实现更精确的类型操作

  3. 标识不可达代码路径,帮助发现逻辑错误

  4. 作为类型运算的底层标识(如条件类型中的最终分支)

四、unknown

未知的值类型。它比 any 更安全,因为使用前必须进行类型检查或断言。

安全容器特性:

java 复制代码
let value: unknown;

// 合法操作
value = 42;          // 可接收任何类型
value = "hello";
value = new Date();

// 非法操作(直接使用会报错)
value.trim();        // Error: Object is of type 'unknown'
value.toFixed(2);    // Error

与 any 的区别

java 复制代码
function exampleAny(val: any) {
  val.trim();        // 不报错(危险!)
}

function exampleUnknown(val: unknown) {
  val.trim();        // Error: 必须类型检查
}

类型收窄实践

java 复制代码
function parseJSON(jsonString: string): unknown {
  return JSON.parse(jsonString);
}

// 使用示例
const data = parseJSON('{"name": "John", "age": 30}');

if (data && 
    typeof data === "object" && 
    "name" in data && 
    typeof data.name === "string" &&
    "age" in data &&
    typeof data.age === "number") {
  // 此时 data 被收窄为 { name: string; age: number }
  console.log(data.name.toUpperCase());  // 安全调用
  console.log(data.age.toFixed(2));       // 安全调用
}

应用场景

假设需要处理动态表格数据时:

java 复制代码
// 从后端接口获取不确定结构的响应
async function fetchDynamicData(): Promise<unknown> {
  const response = await fetch('/api/endpoint');
  return response.json();
}

// 安全使用方式
const data = await fetchDynamicData();

if (typeof data === 'object' && data !== null && 'rows' in data) {
  // 在此处进行更精确的类型断言或类型守卫
  const tableData = data as { rows: Array<{ [key: string]: unknown }> };
  // 进一步处理表格数据...
}

平时怎么用:

  1. 优先使用 unknown 替代 any

  2. 与类型守卫(Type Guard)配合使用

  3. 处理第三方库或外部输入时作为中间类型

  4. 最终通过类型断言收窄到具体类型

至此撒花~

后记

TypeScript主要是类型的理解,多用,多查一下,会发现,也还行。

我是Dignity_呱,来交个朋友呀,有朋自远方来,不亦乐乎呀!深夜末班车

👍 如果对您有帮助,您的点赞是我前进的润滑剂。

以往推荐

Vue性能优化:从加载提速到运行时优化

vue2和Vue3和React的diff算法展开说说:从原理到优化策略

玩转Vue插槽:从基础到高级应用场景(内含为何Vue 2 不支持多根节点)

前端哪有什么设计模式

前端仔,快把dist部署到Nginx上

多图详解,一次性啃懂原型链(上万字)

Vue-Cli3搭建组件库

VuePress搭建项目组件文档

原文链接

juejin.cn/post/751235...

相关推荐
_r0bin_1 小时前
前端面试准备-7
开发语言·前端·javascript·fetch·跨域·class
IT瘾君1 小时前
JavaWeb:前端工程化-Vue
前端·javascript·vue.js
zhang98800001 小时前
JavaScript 核心原理深度解析-不停留于表面的VUE等的使用!
开发语言·javascript·vue.js
potender1 小时前
前端框架Vue
前端·vue.js·前端框架
站在风口的猪11082 小时前
《前端面试题:CSS预处理器(Sass、Less等)》
前端·css·html·less·css3·sass·html5
程序员的世界你不懂2 小时前
(9)-Fiddler抓包-Fiddler如何设置捕获Https会话
前端·https·fiddler
MoFe12 小时前
【.net core】天地图坐标转换为高德地图坐标(WGS84 坐标转 GCJ02 坐标)
java·前端·.netcore
去旅行、在路上3 小时前
chrome使用手机调试触屏web
前端·chrome
Aphasia3113 小时前
模式验证库——zod
前端·react.js
lexiangqicheng4 小时前
es6+和css3新增的特性有哪些
前端·es6·css3