【TypeScript】 any 类型,unknown 类型,never 类型

TypeScript 的三种特殊类型,分别为:any,unknown, never

any 类型

        基本含义

        any 类型表示没有任何限制,该类型的变量可以赋予任意类型的值。

let name:any = "hiyooo"

name.first = "轻奢男装店" //不报错
name.address = ['店铺正在开启中,有意,可以添加微信:Hi_YOOO']
name()  //不报错 ,

变量类型一旦设为any,TypeScript 实际上会关闭这个变量的类型检查。即使有明显的类型错误,只要句法正确,都不会报错。

由于这个原因,应该尽量避免使用any类型,否则就失去了使用 TypeScript 的意义。

*注,但也不是说,就不能使用any 来声明变量的类型

实际开发中,any类型主要适用以下两个场合。

        (1)出于特殊原因,需要关闭某些变量的类型检查,就可以把该变量的类型设为any

        (2)为了适配以前老的 JavaScript 项目,让代码快速迁移到 TypeScript,可以把变量类型设为any。有些年代很久的大型 JavaScript 项目,尤其是别人的代码,很难为每一行适配正确的类型,这时你为那些类型复杂的变量加上any,TypeScript 编译时就不会报错。

        总之,TypeScript 认为,只要开发者使用了any类型,就表示开发者想要自己来处理这些代码,所以就不对any类型进行任何限制,怎么使用都可以。

        从集合论的角度看,any类型可以看成是所有其他类型的全集,包含了一切可能的类型。TypeScript 将这种类型称为“顶层类型”(top type),意为涵盖了所有下层。

 类型推断问题

        对于开发者没有指定类型、TypeScript 必须自己推断类型的那些变量,如果无法推断出类型,TypeScript 就会认为该变量的类型是any

function add(x, y) {
  return x + y;
}

add(1, [1, 2, 3]); // 不报错

        上面示例中,函数add()的参数变量xy,都没有足够的信息,TypeScript 无法推断出它们的类型,就会认为这两个变量和函数返回值的类型都是any。以至于后面就不再对函数add()进行类型检查了,怎么用都可以。

        这显然是很糟糕的情况,所以对于那些类型不明显的变量,一定要显式声明类型,防止被推断为any

        TypeScript 提供了一个编译选项noImplicitAny,打开该选项,只要推断出any类型就会报错。

        此时可以在tsconfig.json中配置 :noImplicitAny

上面命令使用了noImplicitAny编译选项进行编译,这时上面的函数add()就会报错。

污染问题

  any类型除了关闭类型检查,还有一个很大的问题,就是它会“污染”其他变量。它可以赋值给其他任何类型的变量(因为没有类型检查),导致其他变量出错。

        let x :any = "aa"
        let y :number =10;

        y = x;   //不会报错
        y += 10; //不会报错

        y.toFixed(1) //不会报错

        上面示例中,变量x的类型是any,实际的值是一个字符串。变量y的类型是number,表示这是一个数值变量,但是它被赋值为x,这时并不会报错。然后,变量y继续进行各种数值运算,TypeScript 也检查不出错误,问题就这样留到运行时才会暴露。

污染其他具有正确类型的变量,把错误留到运行时,这就是不宜使用any类型的另一个主要原因。


unkown 类型

        基本含义

        它与any含义相同,表示类型不确定,可能是任意类型。

        为了解决any类型“污染”其他变量的问题,TypeScript 3.0 引入了unknown类型,它与any含义相同,表示类型不确定,可能是任意类型,但是它的使用有一些限制,不像any那样自由,可以视为严格版的any

unknownany的相似之处,在于所有类型的值都可以分配给unknown类型。

let name: unknown;

name = true; // 正确
name = 42; // 正确
name = "hiyooo"; // 正确

上面示例中,变量x的类型是unknown,可以赋值为各种类型的值。这与any的行为一致。

unknown类型跟any类型的不同之处在于,它不能直接使用。主要有以下几个限制。

        1). unknown类型的变量,不能直接赋值给其他类型的变量(除了any类型和unknown类型)。

        2).不能直接调用unknown类型变量的方法和属性。

        3).unknown类型变量能够进行的运算是有限的,只能进行比较运算(运算符=====!=!==||&&?)、取反运算(运算符!)、typeof运算符和instanceof运算符这几种,其他运算都会报错。

1).
let name:unknown;

let first_name:string = name;// error 不能将类型“unknown”分配给类型“string”
let age:number  = name; // error 不能将类型“unknown”分配给类型“number”

// 这就避免了污染问题,从而克服了any类型的一大缺点。

2).

let persion:unknown = {name:"hiyooo"}

persion.name;//error 这里会报错。 “person”的类型为“未知”

3).
let hiyooo: unknown = 1;

hiyooo + 1; // 报错 “hiyooo”的类型为“未知”。
hiyooo === 1; // 正确

    那么,怎么才能使用unknown类型变量呢?

答案是只有经过“类型缩小”,unknown类型变量才可以使用。所谓“类型缩小”,就是缩小unknown变量的类型范围,确保不会出错。

let hiyooo: unknown = 1;

if (typeof hiyooo === "number") {
  let r = hiyooo + 10; // 正确
}

这样设计的目的是,只有明确unknown变量的实际类型,才允许使用它,防止像any那样可以随意乱用,“污染”其他变量。类型缩小以后再使用,就不会报错。

总之,unknown可以看作是更安全的any。一般来说,凡是需要设为any类型的地方,通常都应该优先考虑设为unknown类型。

在集合论上,unknown也可以视为所有其他类型(除了any)的全集,所以它和any一样,也属于 TypeScript 的顶层类型。


never 类型

        基本含义

        类型为空,不包含任何值。

         目的

        为了保持与集合论的对应关系,以及类型运算的完整性,TypeScript 还引入了“空类型”的概念,即该类型为空,不包含任何值。

        由于不存在任何属于“空类型”的值,所以该类型被称为never,即不可能有这样的值。

let hiyooo:never;

,变量hiyooo的类型是never,就不可能赋给它任何值,否则都会报错。

never类型的使用场景,主要是在一些类型运算之中,保证类型运算的完整性

如果一个变量可能有多种类型(即联合类型),通常需要使用分支处理每一种类型。这时,处理所有可能的类型之后,剩余的情况就属于never类型。

function fn(x: string | number) {
  if (typeof x === "string") {
    // ...
  } else if (typeof x === "number") {
    // ...
  } else {
    x; // never 类型
  }
}

never类型的一个重要特点是,可以赋值给任意其他类型。

function f(): never {
  throw new Error("Error");
}

let v1: number = f(); // 不报错
let v2: string = f(); // 不报错
let v3: boolean = f(); // 不报错

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值