• 【工具篇】高级 TypeScript 案例


    本文说明:TypeScript 相关文章,了解更多特性。
    网页编辑器https://www.typescriptlang.org/zh/play

    TypeScript

    联合类型

    概念:当某个函数只有一个参数,且希望该参数是某个类型或另一个类型时,就采用 联合类型

    案例:检查某个值是否落在特定区间内

    // 检查某个值是否落在特定区间内
    // 接收 string 值 | number 值
    class RangeValidationBase {
        // 目标区间: 最小值 和 最大值
        constructor(private start: number = 0, private end: number = 10) {}
    
        protected RangeCheck(value: number) : boolean {
            return value >= this.start && value <= this.end;
        }
    
        protected GetNumber(value: string) : number {
            return new Number(value).valueOf();
        }
    }
    
    // 只接受 string | number
    class UnionRangeValidation extends RangeValidationBase {
        IsInRange(value: string | number) : boolean {
            if (typeof value === "number") {
                return this.RangeCheck(value);
            }
            return this.RangeCheck(this.GetNumber(value));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    输出结果:

    // const a = new UnionRangeValidation().IsInRange("123");
    [LOG]: false 
    // const a = new UnionRangeValidation().IsInRange("5");
    [LOG]: true 
    
    • 1
    • 2
    • 3
    • 4

    交叉类型

    交叉可以用于类、接口、泛型、基本类型。

    // 将多个类型合并成一个类型
    class Grid {
        Width: number = 0;
        Height: number = 0;
    }
    
    class Margin {
        Top: number = 0;
        Left: number = 0;
    }
    
    // 交叉
    function ConsolidatedGrid(grid: Grid, margin: Margin) : Grid & Margin {
        const consolidatedGrid = Object.assign({}, grid, margin);
        return consolidatedGrid;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    装饰器

    通过不改变原有的类,去增加功能。

    对于要使用装饰器,请开启 experimentalDecorators ,设置为 true 。

    原始类:

    interface IDecoratorExample {
        AnyoneCanRun(args: string): void;
        AdminOnly(args: string):  void;
    }
    
    class RoleCheck implements IDecoratorExample {
        AnyoneCanRun(args: string): void {
            console.log(args);
        }
        AdminOnly(args: string): void {
            console.log(args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    输出结果:

    // new RoleCheck().AnyoneCanRun("Jemmy as user can running.");
    Jemmy as user can running.
    // new RoleCheck().AdminOnly("Jemmy as Admin can running.")
    Jemmy as Admin can running.
    
    • 1
    • 2
    • 3
    • 4

    根据结果展示两个都能运行成功。

    添加装饰器。

    看到类似下面的这行代码,就表明这是一个装饰器。

    function(target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor)

    函数说明:

    • target 表明目标元素
    • propertyKey 目标元素属性名
    • descriptor 装饰器
    function isInRole(role: string): boolean {
        return user2.roles.some(r => r === role);
    }
    
    // 装饰器
    function Role(role: string) {
        return function(target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) {
            let originalMethod = descriptor.value;
            descriptor.value = function() {
                if (isInRole(role)) {
                    originalMethod.apply(this, arguments);
                    return ;
                }
                console.log(`${user2.user} is not in the ${role} role`);
            }
            return descriptor;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    然后通过 @Role() 添加到需要装饰的函数上面。

    @Role("user")
    AnyoneCanRun(args: string): void {
        console.log(args);
    }
    @Role("admin")
    AdminOnly(args: string): void {
        console.log(args);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    测试结果:

    // const user2 = {user: "Jemmy", roles: ["user"]}
    
    // new RoleCheck().AnyoneCanRun("Jemmy as user can running.");
    Jemmy as user can running
    // new RoleCheck().AdminOnly("Jemmy as Admin can running.")
    Jemmy is not in the admin role
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    混入 mixin

    可以给已存在构造器,添加额外的属性,而不是在原先的基础上修改。
    必要的类型声明:

    type Constructor<T = {}> = new (...args: any[]) => T;
    
    • 1

    根据情况去添加属性,这里以 Deleted 举例。

    function RecordStatus<T extends Constructor >(base: T) {
        return class extends base {
        	// 在这里写属性
            Deleted:  boolean = false;
        }
    }
    
    // 进阶用法: 
    function RecordStatus<T extends Constructor >(base: T) {
        return class extends base {
            deleted: boolean = false;
            
            get Deleted(): boolean {
                return this.deleted;
            }
    
            Delete() : void {
                this.deleted = true;
                console.log("The record has been marked as deleted. ")
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    使用?

    class Personn {
        constructor(private firstName: string, private lastName: string) {}
    }
    
    // 创建一个新的构造器
    const ActivePerson = RecordStatus(Person);
    // 通过新的构造器去创建实例
    let p1 = new ActivePerson("三", "张");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    更多使用方式:可以嵌套。

    其中 Timestame 和 RecordStatus 都是额外添加属性,它们嵌套顺序可以改变。

    const ActivePerson = Timestamp(RecordStatus(Personn))
    
    • 1

    泛型

    这一个知识点很简单,将类型转换成 T 去代替即可。

    class Queue<T> {
        private queue: T[] = [];
    
        push(value: T) : void {
            this.queue.push(value);
        }
    
        pop(): T | undefined {
            return this.queue.shift();
        }
    
        get length() : number {
            return this.queue.length;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    输出结果:

    // const q1 = new Queue();
    // q1.push("1")
    // q..push("2")
    // q1.pop()
    1
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Promise 简单应用

    延时 time 毫秒。

    function ExpensiveWebCall(time: number) : Promise<void> {
        return new Promise((resolve, reject) => setTimeout(resolve, time));
    }
    
    • 1
    • 2
    • 3

    使用?

    console.log("正在处理...")
    ExpensiveWebCall(3000).then(() => {
        console.log("web service end")
    }).catch(() => {
        console.log("appear errors")
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    个人事务管理系统
    Dapr在Java中的实践 之 状态管理
    spring注解开发
    CMakeList.txt
    RabbitMQ消息丢失、消息重复消费、消息顺序性无法保证、消息积压、一致性问题、系统可用性降低等这些常见问题怎么解决
    【uniapp】阿里云OSS上传 [视频上传]
    深入理解蓝牙BLE之“扩展广播”
    Mac使用unrar和rar解压文件
    Java代码审计详解
    元宇宙社交应用,靠什么吸引用户「为爱发电」?
  • 原文地址:https://blog.csdn.net/qq_56402474/article/details/132916185