• 构建类型安全的前端应用


    类型安全问题会影响系统的稳定性。举个例子:

    • 把字符串当成数字进行数学运算,得到错误结果。
    • 用户输入错误数据,导致系统异常。

    以下是常见的类型报错:

    - TypeError: Cannot read property "xx" of undefined
    - TypeError: Cannot set properties of undefined
    - TypeError: 'undefined' is not a function
    
    • 1
    • 2
    • 3

    一. 静态类型安全

    一个经典的类型错误:

    function add(a, b){
        return a + b;
    }
    
    add(1, 1); // 预期值 2
    add('1', 1); // 错误值 '11'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    上面代码在编译时和运行时都不会报错,但是有可能得到错误的结果。

    这类问题是代码本身引入的,在调用函数时传入了错误的数据类型。

    解决方案是使用TypeScript。TypeScript是类型安全的语言,会在编译时检查变量类型

    function add(a:number, b:number){
        return a + b;
    }
    
    add(1, 1); // 编译通过
    add('1', 1); // 编译报错,类型检查不通过
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    二. 动态类型安全

    除了代码本身引入的类型错误,外界输入也是存在风险的。例如,用户输入接口参数等变量,在编译阶段是不知道变量值的,只能在运行时校验。所以我们需要有一个强大的运行时数据类型校验工具,例如zod。

    • 基本数据类型检验

    在zod中,每一种数据类型都有对应的schema实现。

    import { z } from "zod";
    
    // 创建一个字符串schema
    const stringSchema = z.string();
    // 数据校验
    stringSchema.parse("abc"); // => "abc" 
    stringSchema.parse(123); // => throws ZodError
    
    // 数据校验(不会抛异常)
    stringSchema.safeParse("abc"); // => { success: true; data: "abc" }
    stringSchema.safeParse(123); // => { success: false; error: ZodError }
    
    // 常见的schema如下:
    z.string(); 
    z.number(); 
    z.bigint(); 
    z.boolean(); 
    z.date(); 
    z.symbol();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    对于复杂的数据类型,例如对象,则可以通过多个schema组合的方式实现。

    • 复杂数据类型检验
    import { z } from "zod";
    
    // 创建一个对象schema
    const userSchema = z.object({ username: z.string(), age: z.number()}); 
    // 数据校验
    userSchema.parse({ username: "Ludwig", age: 10 }); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 实践案例

    下面以一个用户信息表单为例。

    首先,设计出用户信息如下:

    {
        "姓名": 最长32位字符串,必填
        "年龄": 正整数,必填
        "邮箱": 邮箱地址,必填
        "头像": 图片链接,可选
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后,定义表单schema:

    export const userSchema = z.object({
      name: z.string().max(32),
      age: z.number({required_error: '请输入年龄'})
            .int({message:'年龄是一个正整数'})
            .positive({message:'年龄是一个正整数'}),
      email: z.string().email(),
      image: z.string().url(),
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    最后,在提交表单时校验数据。

    // extract the inferred type 
    // { name: string, age: number, email: string, image: string}
    type UserType = z.infer<typeof userSchema>; 
    function submit(UserType formData){
        const data = userSchema.parse(formData);
        // ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    总结

    对于Web应用来说,类型安全问题无处不在。例如,代码本身引入的类型错误;用户输入的数据类型不对;或者接口传参的类型错误等等。这些都会影响系统的稳定性

    所以,我们要构建类型安全的应用,包括以下两点:

    • 第一,静态类型安全。使用TypeScript等类型安全的语言,在编译阶段检查类型。
    • 第二,动态类型安全。使用zod等检验工具,在运行时检验数据。
  • 相关阅读:
    【Linux网络编程】信号和定时器
    【Python 4】列表与元组slice切片 迭代 列表生成式 生成器generator 迭代器Iterator对象
    【一】情感对话 Towards Emotional Support Dialog Systems 论文阅读
    Java进阶知识
    python设计模式11:观察者模式
    普冉PY32系列(九) GPIO模拟和硬件SPI方式驱动无线收发芯片XL2400
    java环境安装与配置
    CocosCreator 面试题(十二)Cocos Creator Label 的原理以及如何减少Drawcall
    【对比】文心一言对飚ChatGPT实操对比体验
    一般做家庭用电的考什么样式的电工证?应急管理厅低压电工
  • 原文地址:https://blog.csdn.net/weixin_39805244/article/details/132792466