首页IT科技typescript的类(TypeScript类型anynevervoid和unknown使用场景区别)

typescript的类(TypeScript类型anynevervoid和unknown使用场景区别)

时间2025-06-21 01:53:02分类IT科技浏览4606
导读:前言 不知道初学TypeScript的同学会不会和我一样被any,unknown,never和void这几个类型搞得晕头转向呢?如果你也有同样的困惑,那么就请跟着本篇文章彻底搞懂这四种类型的区别吧。...

前言

不知道初学TypeScript的同学会不会和我一样被any           ,unknown                  ,never和void这几个类型搞得晕头转向呢?如果你也有同样的困惑      ,那么就请跟着本篇文章彻底搞懂这四种类型的区别吧           。

any

首先给大家介绍的是any类型        ,我相信一些从JavaScript转TypeScript的同学一定不会对这个类型感到陌生                  ,因为它是我们将JavaScript代码重构为TypeScript代码的银弹         ,甚至有些程序员由于过度依赖any类型活生生将TypeScript写成了AnyScript                  。

用法

当我们将某个变量定义为any类型后     ,TypeScript将会跳过对这个变量的类型检查:

let something: any = Hello World! something = 18 // ok! ts不会管any的类型检查 something = true // ok! ts不会管any的类型检查

在上面的代码中一般来说如果something被初始化为一个字符串类型后                  ,是不可以被赋值为number或者boolean类型的            ,不过由于我们声明了它的类型是any所以TypeScript就完全不管这个对象的类型检查了      。除了这个  ,你还可以随意访问这个any对象上面的任意属性                 ,即使它们不存在:

let something: any = Hello World! something.notExistMethod() // ok! something.notExistProperty.name() // ok!

在上面的代码中我们可以访问any类型对象的任意属性               ,并且这个any是具有传递性的,也就是说something后面无论跟了多少个属性访问              ,它们的类型都是any        。

使用场景

any一般的使用场景有下面这些:

代码从JS迁移到TS:这个时候使用any我们可以将重构快速推进而不用陷入无边无尽的类型错误里面去                  。这里值得一提的是any只能作为临时过渡方案                  ,我们最后的结果一定是确保代码尽可能少any的出现 我们不关心对象的类型:例如我们实现了一个print函数   ,这个函数底层调用console.log           ,这个时候其实我们不需要关心传进来的具体数据类型是什么                  ,我们只需要一股脑将它传递给console.log函数即可      ,这个时候我们就可以将函数的参数类型设置为any了

类型缺失或者补全困难:这种情况一般发生在我们使用了第三方JS编写库的时候        ,我们没有办法知道某个导出的函数的具体类型                  ,这时我们需要定义一些全局的类型垫片:

// shim.d.ts declare module "unknown-type-lib" { export function someFunction(input: string): any }

注意:虽然any很方便         ,可是我们还是需要想办法避免代码中出现any类型     ,这是因为any跳过了所有的类型检查                  ,而这会给我们带来一些潜在的安全问题         。最坏的情况是整个代码除了any没有其它有意义的类型            ,这个时候还不如直接编写JavaScript代码来得实在  ,既然我们选择了TypeScript                 ,我们还是希望它可以真真实实为我们带来收益的               ,因此当我们碰到一些很难编写的类型时,最好的做法不是写any              ,而是询问一些资深的工程师或者网上查找资料来解决这个问题     。

unknown

上面我们说到了any会跳过所有的类型问题                  ,而这其实会为日后的代码维护和开发埋下巨大的安全隐患                  。为了解决any的问题   ,TypeScript在3.0版本引入了unknown类型           ,它可以理解为类型安全的(type-safe)any            。

用法

和any一样                  ,任何类型都可以赋值给unknown类型的对象:

let vAny: any = Hello World! // ok! any对象接受任何类型 let vUnknown: unknown = Hello World! // ok! unknown对象接受任何类型的对象

和any不一样      ,unknown类型的对象不可以直接赋值给其它非unknown或any类型的对象        ,并且不可以访问上面的任何属性:

let vAny: any = Hello World! let vUnknown: unknown = Hello World! let vNumberForAny: number = vAny // ok! any可以直接赋值给其它任意类型 let vNumberForUnknown: number = vUnknown // error! unknown不可以直接赋值给其它非any和unknown类型的对象 vAny.toLocaleLowerCase() // ok! any可以访问所有的属性 vUnknown.toLocaleLowerCase() // error! unknown对象不可以直接访问上面的属性

那么应该怎样才能使用unknown类型的变量呢?答案很简单                  ,那就是你需要先推断出对象的类型         ,才能使用     ,推断的方式有很多种                  ,包括typeof和as assertion等其他type guard方法:

let vUnknown: unknown = abc // 使用typeof推断出vUnknown的类型是string if (typeof vUnknown === string) { vUnknown.toLocaleUpperCase() // ok! 因为能进入这个if条件体就证明了vUnknown是字符串类型! } let vNumberForUnknown: number = vUnknown as number // unknown类型一定要使用as关键字转换为number才可以赋值给number类型

使用场景

由于unknown基本可以替代any            ,所以在任何any适用的场景  ,都应该优先使用unknown  。使用了unknown后                 ,我们既允许某个对象储存任意类型的变量               ,同时也要求别人在使用这个对象的时候一定要先进行类型推断                 。

never

never不像前面那几个类型一样常用,甚至有些同学可能一开始压根就不知道这个类型存在的意义是什么               。我们知道TypeScript在解析我们的代码时会对代码进行类型推断              ,并且在代码流不断深入的时候                  ,类型会从较为宽泛的类型(例如any)一直推断到较为具体的类型   ,而这么推断下去是会有个终点           ,这个终点就是不存在的                  ,不可能发生的类型      ,也就是类型系统的底部类型(bottom type)        ,而never就是TypeScript的底部类型。

用法

never类型只接受never类型的对象                  ,甚至万金油any类型都不可以赋值给never类型              。

let vAny: any = 1 let vNever: never = vAny // error! never除了自己谁不都接受!

一般当我们想表示某个函数永远不会返回时         ,可以使用never类型     ,例如下面的例子:

// 因为这个是无限循环                  ,我们可以使用never作为返回值表示它永远不会返回 function foreverLoop(): never { while(true) {} } // 因为这个函数会抛出异常            ,所以也是不会返回的 function crashFunc(): never { throw new Error(this function will crash) }

使用场景

never类型的一个最大的作用就是帮我们对类型进行exclusive check  ,例如下面这个例子:

interface QA { kind: qa bug: number } interface Developer { kind: developer hair: number } type TechDude = QA | Developer function printTechDude(h: TechDude) { if (h.kind === qa) { console.log(h.bug) } else if (h.kind === developer) { console.log(h.hair) } else { let exclusiveCheck: never = h // 由于这个代码永远也到达不了                 ,所以h的类型被自动推断为never } }

上面的代码现在是没有问题的               ,不过假如某一天我们新增了一个新的PM类型,而忘记在printTechDude函数里面处理这个新类型的话              ,上面的代码会报错:

interface QA { kind: qa bug: number } interface Developer { kind: developer hair: number } interface PM { kind: pm features: number } // TechDude多了一个PM类型 type TechDude = QA | Developer | PM function printTechDude(h: TechDude) { if (h.kind === qa) { console.log(h.bug) } else if (h.kind === developer) { console.log(h.hair) } else { let exclusiveCheck: never = h // error! 因为PM类型不可以赋值给never类型 } }

上面代码报错的原因是TechDude这个类型在else这个代码体里面已经被TypeScript收拢为PM类型                  ,所以不再是never类型了                  。要去掉这个错误   ,我们需要在printTechDude函数里面额外加多一个else if(h.kind === pm)的判断:

function printHuman(h: TechDude) { if (h.kind === qa) { console.log(h.bug) } else if (h.kind === developer) { console.log(h.hair) } else if (h.kind === pm) { console.log(h.features) }else { let exclusiveCheck: never = h } }

也正是因为exclusive check的存在我们才可以在类型变化的时候及时发现           ,避免问题留到了线上环境   。

void

void其实可以理解为null和undefined的联合类型                  ,它表示空值           。

用法

我们一般不会声明某个值的类型为void      ,因为它表示这个值只能是undefined或者null(strictNullChecks没被指定):

let vVoid: void = undefined

void一个更加常见的使用场景是表示某个函数没有任何返回值:

function noReturnValue(): void { console.log(hello) // 代码没有任何返回值        ,所以这个函数的返回值是void }

使用场景

这里只想说明一下void和never的区别                  。void表示空值                  ,也就是null或者undefined         ,而never则表示永远都不会出现的值      。

总结

本篇文章通过例子给大家介绍了TypeScript中几个容易混淆的类型any     ,unknown                  ,never和 void            ,希望能帮助有需要的人解答到疑惑  ,更多关于TypeScript类型使用场景的资料请关注本站其它相关文章!

声明:本站所有文章                 ,如无特殊说明或标注               ,均为本站原创发布        。任何个人或组织,在未征得本站同意时              ,禁止复制            、盗用                 、采集      、发布本站内容到任何网站         、书籍等各类媒体平台                  。如若本站内容侵犯了原著者的合法权益                  ,可联系我们进行处理         。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
看新闻哪个app赚钱快(什么软件看新闻赚钱快-还在“刷新闻赚现金”?当心碰触到法律底线)