TS类型断言?

211 阅读2分钟

什么是类型断言?

就是可以用来手动指定一个值的类型,即允许变量从一种类型更改为另一种类型

语法格式

(1)<类型>值

(2)值 as 类型

有人说,类型断言更像是类型的选择,而不是类型的转换

案例一

// 这里,参数是联合类型,可以有两种类型,但是,ts编译的时候,val.length就会报错,因为假定参数是number,此时就不成立,因为后面代码编译时也不确定这个参数是什么类型。

function func(val:string|number):number{        
     if(val.length){
          return val.length
       }else{
            return val.toString().length
       }
 }
 
//  所以,为了解决这种问题 ,ts里就有了类型断言
//  有个说法,<值 as 类型> 

方式一: <值 as 类型> 会更好,在jsx 语法中 ,只支持这种写法

function  func(val:string|number):number{
    if(val as  string).length){
          return (val as string).length
     }else{
          return val.toString().length
     }
}

方式二 : <类型>值
function func(val:string|number):number{

  if((<stringval>).length){
      return (<string>val).length
  }else{
      return val.toString().length
  }
}

 

类型断言的限制(特点)

1、联合类型可以被断言为其中一个类型

2、父类可以被断言为子类

3、任何类型都可以被断言为any

4、any 可以被断言为任何类型

但,类型之间的断言确是有限制的。若类型A能兼容 ,类型B ,也可以将B断言为A
TS是结构类型系统,类型之间的对比只会比较它们最终的结构,而会忽略它们定义时的关系
// 尽管`Animal`、`Cat`定义时并没有任何关系,但结构上可以理解为`Cat`继承于`Animal`,此时二者可以互相断言

// (1)允许 `animal as cat` 是因为父类可以被断言为子类。  (2)允许 `cat as animal` 是因为子类拥有父类的所有属性和方法,调用也不会出问题

   interface Animal{
     name:string;
   }
   
   interface Cat{
     name:string;
     run():void;
   }
  const tom:Cat={
     name:"tom",
     run(){
        console.log("running")
     }
  } 
  
  const  animal:Animal=tom

个人觉得,断言的目标类型,应该是包含当前类型

最后,类型断言只会影响TS编译时的类型,类型断言语句会在编译结果中删除断言其实更像是对编译器的欺骗,是为了让编译通过,不代表运行时不报错,所以,对值各种可能的类型的还是要有相应的处理逻辑。在实际项目中,对于类型的断言也会变得更为复杂。