个人技术分享

image.png

一、什么是断言

  • 断言:其实就是告诉 TS,我知道我自己在做什么,不要你管

image.png

  • 因为我们在 TS 的开发过程中,TS 会识别我们写的所有的内容,然后会傻傻的根据代码去识别你写的内容
  • 先来看个例子吧
const box = document.querySelector('.box')
console.log(box.innerHTML)
  • 一段看似简单的代码,谁都认识
  • 但是一旦运行起来

image.png

  • 这是什么鬼,为什么会报错呢
  • 浅浅的解释一下
    • 我们通过 querySelector 方法从页面上获取一个元素
    • 这是没有问题的,但是根据语法,我们获取到的有可能是一个元素
    • 也有可能是 null,也就是页面上根本没有这个元素
    • 但是 TS 在识别的时候,其实是傻傻的,不会去识别你的 html 元素,也不会去捕获你的页面
    • 只是单纯的看你书写的 ts 代码,那么他就会认为,你有可能获取不到元素
    • 这个时候,就会给你提示错误了
    • 因为如果万一真的是 null,那么肯定是不能调用 innerHTML 属性的
    • 错误也就出现了
  • 当我们开发的时候,在写代码的时候,只要我们准确的告诉他,我这个代码一定能获取到元素,你不要管东管西的,那么 TS 就不会在提示错误了
    • 就像上面的代码,只要你在使用 innerHTML 的时候,准确的告诉他
    • 我的 box 一定是一个 HTML 元素,那么就一定能调用 innerHTML 这个属性
    • 这个时候,TS 就不会给你提示错误了

image.png

二、类型断言

方式1: 利用 as 书写断言

  • 语法 : 数据 as 类型
const box = document.querySelector('.box')
console.log((box as HTMLDivElement).innerHTML)

方式2 : 利用 <> 书写断言

  • 语法 : <类型>数据
const box = document.querySelector('.box')
console.log((<HTMLDivElement>box).innerHTML)
  • 这就是对一个数据进行类型断言
  • 也就是在开发的过程中
  • 讲某一个数据断定为某一个类型
  • 这样就可以直接按照该数据类型去调用属性和方法了

三、非空断言

  • 也就是在开发的过程中,忽略有可能出现的 undefined 和 null 类型
  • 这里我们使用 ! 来做这个事情
const box = document.querySelector('.box')
console.log(box!.innerHTML)
  • 注意
    • 当 box 只有可能是 一个内容 或者 undefined 或者 null 的时候
    • 我们可以用 ! 进行断言,也就是告诉他,box 不可能是 null 或者 undefined
    • 利用 ! 排除了 undefined 和 null 的可能

四、确定赋值断言

  • 在开发中还有这样一种情况,就是我们在初始定义某一个变量的时候,有可能是不赋值的
  • 在后面的代码或者函数内对其进行赋值,然后再使用
// 初始化的时候不进行赋值
let n: number

// 通过调用这个函数对 n 进行赋值操作
function init () { n = 100 }
init()

// 这里使用一下 x
console.log(x.toFixed(2))
  • 然后我们就发现,TS 又提示错误了

image.png
image.png

  • 这是因为 TS 不太清楚你的 init 函数调用以后会对 x 进行赋值
  • 所以就会告诉你,你还没有赋值呢,就调用了 toFixed 方法
  • 这个时候,我们就可以使用确定赋值断言,还是使用 !
// 初始化的时候不进行赋值
let n!: number

// 通过调用这个函数对 n 进行赋值操作
function init () { n = 100 }
init()

// 这里使用一下 x
console.log(x.toFixed(2))
  • 在初始化的时候,给变量后面加一个 !
    • 也就是告诉 TS,这个变量我一定会百分之一万赋值的,你少管
    • 这样今后在遇到你使用 x 这个变量的时候
    • TS 就会默认认为他一定有值
    • 也就不会提示错误了

五、const 断言

  • 这个有点和我们定义变量的关键字差不多,但是又不太一样,小伙伴不要搞混淆了哦
  • 我们先来看这个代码把
let n: number = 100 as const
let s: string = 'hello world' as const
  • 这样一来,我们定义的 n 和 s 就不能被更改了

image.png

  • 我直接用 const 定义变量不好吗,为什么 … ( 如果不能骂街,那我无话可说 )
  • hold on … hold on !!
  • 我们再来看下一段代码
const obj = { name: 'Jack', age: 18 }
  • 这个就是用 const 定义的一个变量,只不过值是一个引用数据类型了
  • 我们的 const 只能保证 obj 不会被改变,但是 obj 内部的子级数据是不会被限制的
  • 如果我们想让 obj 内的每一个成员都是只读的属性,不允许被更改呢
  • 只能是在书写接口的时候,把每一个属性都定义为 readonly
  • O(∩_∩)O哈哈~,我的 const 断言有用武之地了
const obj = { name: 'Jack', age: 18 } as const
  • 这样一来,我们 obj 内 所有的子级数据就都不能被更改了

image.png

  • 注意:
    • const:是 ES6 中定义变量的关键字,反应当前定义的是一个常量,不允许被更改,但是对于引用数据类型来说,起子属性还是可以被修改的
    • as const:TS 内的语法,告诉 TS,被断言的内容不管是自己本身还是其子属性都不允许被修改,TS 就会对每一个层级的数据进行最严格的判断和限制