• TypeScript 第二章:枚举与断言



    Enums 枚举

    枚举在程序语言及 mysql 等数据库中广泛使用

    • 不设置值时,值以 0 开始递增

    下面是使用枚举设置性别

    enum SexType {
        boy,
        girl
    }
    
    const obj = {
        name: 'hj',
        sex: SexType.boy
    }
    console.log(obj); // { name: 'hj', sex: 0 }
    console.log(SexType.girl); // 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    • 当某个字段设置数值类型的值后,后面的在它基础上递增
    enum SexType {
        boy = 1,
        girl
    }
    const obj = {
        name: 'hj',
        sex: SexType.boy
    }
    console.log(obj); // { name: 'hj', sex: 1 }
    console.log(SexType.girl); // 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    • 可以将值设置为其他类型
    enum SexType {
        boy = '男',
        girl = '女'
    }
    
    const obj = {
        name: 'hj',
        sex: SexType.boy
    }
    console.log(obj); // { name: 'hj', sex: '男' }
    console.log(SexType.girl); // 女
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    as 断言

    as 断言的意思就是用户断定这是什么类型,不使用系统推断的类型,说白了就是 我说是什么,就是什么

    下例中 TS 会根据函数推断变量 data 的类型是 string | number

    const hj = (a: boolean) => {
        return a ? 'hj' : 18
    }
    
    let data = hj(true) // let data: string | number
    
    • 1
    • 2
    • 3
    • 4
    • 5

    我们可以由开发者来断定(断言)这就是字符串,这就是断言

    const hj = (a: boolean) => {
        return a ? 'hj' : 18
    }
    
    let data = hj(true) as string // let data: string
    
    • 1
    • 2
    • 3
    • 4
    • 5

    也可以使用下面的断言语法

    const hj = (a: boolean) => {
        return a ? 'hj' : 18
    }
    
    let data = <string>hj(true) // let data: string
    
    • 1
    • 2
    • 3
    • 4
    • 5

    const 断言

    let & const

    • const 保证该字面量的严格类型
    • let 为通用类型比如字符串类型
    const hj = 'hj' // const hj: "hj"
    let hk = 'hj' // let hk: string
    
    • 1
    • 2

    const

    const断言告诉编译器为表达式推断出它能推断出的最窄或最特定的类型,而不是宽泛的类型

    • 字符串、布尔类型转换为具体值
    • 对象转换为只读属性
    • 数组转换成为只读元组

    下面限定 user 类型为最窄类型houdunren.com

    let user = 'hj' as const
    user = 'hk' // 不能将类型“"hk"”分配给类型“"hj"”
    
    // 与以下很相似
    let user: 'hj' = 'hj'
    user = 'hk' // 不能将类型“"hk"”分配给类型“"hj"”
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    对象转换为只读属性

    let hj = {name: 'hj', age: 18} as const
    
    hj.name = 'hk' // 无法分配到 "name" ,因为它是只读属性
    
    • 1
    • 2
    • 3

    当为变量时转换为变量类型,具体值是转为值类型

    let a = 'a'
    let b = 'b'
    
    let hj = [a, b, 'hj', 18] as const // let hj: readonly [string, string, "hj", 18]
    hj[0] = 'c' // 无法分配到 "0" ,因为它是只读属性
    
    • 1
    • 2
    • 3
    • 4
    • 5

    数组赋值

    变量 f 得到的类型是数组的类型 string|number,所以只要值是这两个类型都可以

    let a = 'hj'
    let b = 18
    
    let hj = [a, b] // let hj: (string | number)[]
    let c = hj[1] // let c: string | number
    c = 'hk' // 不报错,因为类型是 string | number
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    使用 const 后会得到值的具体类型,面不是数组的类型

    let a = 'hj'
    let b = 18
    
    let hj = [a, b] as const // let hj: readonly [string, number]
    let c = hj[1] // let c: number
    c = 'hk' // 报错,不能将类型“string”分配给类型“number”
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    也可以使用以下语法

    let a = 'hj'
    let b = 18
    
    let hj = <const>[a, b] // let hj: readonly [string, number]
    let c = hj[1] //let c: number
    c = 'hk' // 报错,不能将类型“string”分配给类型“number”
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    解构

    下面解构得到的变量类型不是具体类型,而是数组类型,比如变量 y 的类型是 string | (() => void)

    这在写项目时是不安全的,因为可以将 y 随时修改为字符串,同时也不会有友好的代码提示

    function hj() {
      let a = 'hj'
      let b = (x: number, y: number): number => x + y
      return [a, b]
    }
    let [n, m] = hj() // 变量 m 的类型为 string | (() => void)
    
    m(1, 6) // 报错:因为类型可能是字符串,所以不允许调用
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    可以断言 m 为函数然后调用

    function hj() {
      let a = 'hj'
      let b = (x: number, y: number): number => x + y
      return [a, b]
    }
    let [n, m] = hj()
    console.log((m as Function)(1, 2))
    // 使用以下类型声明都是可以的
    console.log((m as (x: number, y: number) => number)(1, 5)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    可以在调用时对返回值断言类型

    function hj() {
      let a = 'hj'
      let b = (x: number, y: number): number => x + y
      return [a, b]
    }
    
    let [n, m] = hj() as [string, (x: number, y: number) => number]
    console.log(m(9, 19))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    也可以在函数体内声明返回类型

    function hj() {
      let a = 'hj'
      let b = (x: number, y: number): number => x + y
      return [a, b] as [typeof a, typeof b]
    }
    
    let [n, m] = hj()
    console.log(m(9, 19))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    使用 as const 就可以很高效的解决上面的问题,可以得到具体的类型,来得到更安全的代码,同时会有更好的代码提示

    function hj() {
      let a = 'hj'
      let b = (): void => {}
      return [a, b] as const
    }
    
    const [x, y] = hj() // 变量 y 的类型为 () => void
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    因为 const 是取值的类型,下面代码虽然不报错,但此时 b 的类型已经是 字符串或函数,所以像下面一样在函数调用时 as const 没有意义

    function hj() {
      let a = 'hj'
      let b = (x: number, y: number): number => x + y
      return [a, b]
    }
    
    const [n, m] = [...hj()] as const
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    非空断言

    下面的示例获取的值可能为 HTMLDivElement 或 null,所以直接分配类型“HTMLDivElement”将报错误

    下例操作需要开启 tsconfig.json 的配置项 strictNullChecks 字段为 true

    const el: HTMLDivElement = document.querySelector('.hj')
    console.log(el.id);
    
    • 1
    • 2

    可以使用 as 断言类型

    const el: HTMLDivElement = document.querySelector('.hj') as HTMLDivElement
    console.log(el.id);
    
    • 1
    • 2

    在值后面使用 ! 来声明值非 null

    const el: HTMLDivElement = document.querySelector('.hj')!
    console.log(el.id);
    
    • 1
    • 2

    DOM

    为了演示示例我们创建 html 文件如下

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <title>TS</title>
            <script src="1.js" defer></script>
        </head>
        <body>
            <div class="hj">ts</div>
            <button id="bt">插入元素</button>
        </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    类型推断

    对于获取的标签对象可能是为 null 也可能是该标签类型

    • body 等具体标签可以准确标签类型或 null
    • 根据 class 等获取不能准确获取标签类型,推断的类型为 Element | null
    const body = document.querySelector('body') // const body: HTMLBodyElement | null
    
    • 1

    下面是根据 class 获取标签结果是 ELement 并不是具体的标签,因为根据 class 无法确定标签类型

    const el = document.querySelector('.hj') // const el: Element | null
    
    • 1

    断言处理

    使用as 将类型声明为 HTMLAnchorElement 则 TS 会将其按 a 链接类型处理

    • 现在所有的提示将是 a 链接属性或方法
    const el = document.querySelector('.hj') as HTMLAnchorElement // const el: HTMLAnchorElement
    console.log(el.href);
    
    • 1
    • 2

    下例中的 DOM 类型会报错,因为.hd 是 Element 类型,而构建函数参数 el 的类型是 HTMLDivElement

    class Hj {
        constructor(el: HTMLDivElement) {
        }
    }
    const el = document.querySelector('.hj'); // el: Element
    new Hj(el)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这时可以使用 as 断言处理,明确告之获取的值类型是 HTMLDivElement

    class Hj {
        constructor(el: HTMLDivElement) {
        }
    }
    const el = document.querySelector('.hj') as HTMLDivElement;
    new Hj(el)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    事件处理

    下面提取按钮元素并添加事件,实现插入元素的功能

    const hj = document.querySelector('#hj') as HTMLButtonElement
    
    hj.addEventListener('click', (e: Event) => {
        e.preventDefault() // 因为设置了 e 的类型,所以会有完善的提示
        console.log(e);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    5-Dubbo架构设计与底层原理-服务导出源码分析(中)
    golang convert json string to map
    小程序转App最便捷的方法,附实操
    如何获取淘宝sku详细信息 API接口
    雷电4模拟器安装xposed框架(2022年)
    C++模拟实现——红黑树封装set和map
    SpringBoot项目的创建(一):通过idea的Spring Initializr来创建(需联网以下载SpringBoot相关的模板)
    2023国赛数学建模B题思路分析 - 多波束测线问题
    Servlet
    MySQL如何在不知道密码的情况下知道并修改密码
  • 原文地址:https://blog.csdn.net/qq_41887214/article/details/125514211