TS(三)TS(三)其他常用类型

发布时间 2023-12-18 14:01:19作者: Tod4

元组

元组定义需要指定每一个元素的类型:

let arr:[number, boolean] = [1, true]
arr[0] = 2
越界则推断为交叉类型
let arr:[number, boolean] = [1, true]
arr.push(2)
console.log(arr)

如果不想修改,不能使用const(只是元组不可变,内容仍能够修改),需要标识为read Only

let arr: readonly [number, boolean] = [1, true]
arr.push(2)
console.log(arr)
添加?则推断为联合类型
let arr: readonly [x:number, y?:boolean] = [1]
console.log(arr)

即y: boolean | undefined

获取元素类型
let arr: readonly [x:number, y?:boolean] = [1, true]
type first = typeof arr['length']

枚举

数字枚举
enum Color {
    red,
    blue,
    green
}

console.log(Color.red)
console.log(Color.blue)
console.log(Color.green)

数字枚举默认值为 0, 1, 2

增长枚举
enum Color {
    red = 3,
    blue,
    green
}

console.log(Color.red)
console.log(Color.blue)
console.log(Color.green)

增长枚举按照第一个值进行递增

字符串枚举

字符串无法递增,需要全部定义

异构枚举

即混合类型元素的枚举

接口枚举的混合使用
enum Color {
    red = 3,
    blue,
    green
}

interface A {
    color: Color.red
}

let obj:A = {
    color: Color.red
}

以此约束接口定义

const枚举
  • 正常编译,会将枚举类编译为一个对象
enum Types {
    success,
    fail
}
let code:number = 0
if(code === Types.success) {

}
var Types;
(function (Types) {
    Types[Types["success"] = 0] = "success";
    Types[Types["fail"] = 1] = "fail";
})(Types || (Types = {}));
var code = 0;
if (code === Types.success) {
}
  • const则会编译为常量
var code = 0;
if (code === 0 /* Types.success */) {
}
反向映射

即可以通过value获取key值

enum Types {
    success,
    fail
}
let num:string = Types[0]
console.log(num)

success

类型推断

  • 声明的时候进行赋值,会被推断为后面赋值的类型
  • 声明的时候不进行赋值,会被推断为any

type 类型别名

type s = string | number
let str:s = "123"

甚至是函数、对象、数组

type f = (name:string, age:number) => void
type和interface的区别
  1. type不能像interface一样继承,只能通过&交叉类型
  2. interface不能像type一样使用联合类型
type中的extends

type中的extends是包含的意思,如下1是number的子集,所以三目表达式返回的是1

type num = 1 extends number ? 1 : 0

let number:num = 2

子集排列顺序为:

1 any unkown
2 Object
3 Number
4 number string
5 never

never

  • never在ts中表示永远无法到达的类型,如
let num: number & string
function fu():never {
    // while(true) {
    //    
    // }
    throw new Error()
}
  • never类型属于最底层的类型,当使用联合类型的时候会被忽略
let a:number | never
  • 可以作为一个兜底的逻辑,防止出错
type A = '唱' | '跳' | 'rap' | '篮球'

function kun(value: A) {
    switch (value) {
        case '唱':
            break
        case '跳':
            break
        case 'rap':
            break
        // case '篮球':
        //     break
        default:
            const error: never = value
            break
    }
}

正常情况下,写完所有的case,default永远不会到达,否则就会报错

symbol类型

  • value = Symbol(key)会为key(可以重复)生成一个唯一的value
  • Symbol.for(number | string | undefined)会从symbol查看是否使用过相同的key,用过则直接返回value没有则生成新value
let a1:symbol = Symbol(1)
let a2:symbol = Symbol(1)
console.log(a1 === a2) // false
console.log(Symbol.for('1') === Symbol.for('1')) // true
  • Symbol本质是一个key-value键值对的key,只不过它允许两个key重复
let a1:symbol = Symbol(1)
let a2:symbol = Symbol(1)


let Obj = {
    name: 'zhangsan',
    [a1]: '123',
    [a2]: '456'
}

console.log(Obj)

由于symbol的本质是key,所以这里需要添加索引签名[]才能设置value

PS E:\File\myNote\TypeScript> ts-node .\basis.ts
{ name: 'zhangsan', [Symbol(1)]: '123', [Symbol(1)]: '456' }

map set集合

set自动去重
  • 构造器参数只能是数组
let set: Set<number> = new Set([1, 2, 3, 4, 5, 1, 1, 1]);
console.log(set)
PS E:\File\myNote\TypeScript> ts-node .\basis.ts
Set(5) { 1, 2, 3, 4, 5 }
map键值对存储
let map:Map<string, number> = new Map<string, number>()
map.set("1", 1)
console.log(map)
PS E:\File\myNote\TypeScript> ts-node .\basis.ts
Map(1) { '1' => 1 }

生成器和迭代器

生成器
  • done为true表示生成器结束,value既可以为同步方法也可以是异步方法
function* gen() {
    yield Promise.resolve('123')
    yield 456
    yield 789
    yield 1011
}

const m = gen()
console.log(m.next())
console.log(m.next())
console.log(m.next())
console.log(m.next())
console.log(m.next())
{ value: Promise { '123' }, done: false }
{ value: 456, done: false }
{ value: 789, done: false }
{ value: 1011, done: false }
{ value: undefined, done: true }

迭代器
  • 对于数组mapset以及类似function的argumenthtml的document的querySelect得到的伪数组,原型上都包含一个迭代器:
Symbol(Symbol.iterator): ƒ values()
  • 获取迭代器实现迭代

    let arr = [1, 2, 3]
    
    const each = (value: any) => {
        let It:any = value[Symbol.iterator]()
        // 设置的一个初始值,方便下面判断的
        let next:any = {done : false}
        while(!next.done) {
            next = It.next()
            if(!next.done) {
                console.log(next.value)
            }
        }
    }
    
    each(arr)
    
    

    value[Symbol.iterator]()

    value[Symbol.iterator]表示根据索引标签获取Symbol.iterator的key的value值,而这个值是一个函数

  • 上面的这一段实现,正是类似于map的迭代器语法糖遍历原理

迭代器语法糖: for of
let arr = [1, 2, 3]

// const each = (value: any) => {
//     let It:any = value[Symbol.iterator]()
//     let next:any = {done : false}
//     while(!next.done) {
//         next = It.next()
//         if(!next.done) {
//             console.log(next.value)
//         }
//     }
// }
//
// each(arr)

for(let num of arr) {
    console.log(num)
}
对象类型不能使用迭代器的解决方案:自己加一个
let obj:object = {
    max: 5,
    current: 0,
    [Symbol.iterator]() {
        return {
            next() {
                if(this.current == this.max) {
                    return {
                        next: undefined,
                        done: true
                    }
                } else {
                    return {
                        value: this.current++,
                        done: false
                    }
                }
            }
        }
    }
}
for(let num of obj) {
    console.log(num)
}