背景

大家出来写 Bug 代码的,难免会出 Bug。

文章背景就发生在一个 Bug 身上,

有一天,测试慌张中带着点兴奋冲过来: 测试:“xxx 系统前端线上出 Bug 了,点进 xx 页面一片空白啊”。 我:“纳尼?我写的 Bug 怎么会出现代码呢?”。

虽然大脑一片空白,但是锅还是要背的。 进入页面一看,哦豁,完蛋,cannot read the property 'xx' of undefined。确实是前端常见的报错呀。

背锅王,我当定了?未必。

我眉头一皱,发现事情并不是那么简单,经过一番猛如虎的操作之后,最终定位到问题是:后端接口响应的 JSON 数据中,一个嵌套比较深的字段没有返回,即前端只读到了 undefined

咱按章程办事,后端提供的接口文档指定了数据结构,那你没有返回正确数据结构,这就是你后端的锅,虽然严谨点前端也能捕获到错误进行处理,但归根到底,是你后端数据接口处理有问题,这锅,我不背。

甩锅又是一门扯皮的事情,杀敌一千自伤八百,锅已经扣下来了,想甩出去就难咯,。

唉,要是在接口出错的时候,能立刻知道接口数据出问题,先发制人,马上把锅甩出去那就好咯。

这就是本文即将要讲述的 “Typescript 运行时数据校验”。

为什么要运行时校验数据?

众所周知,TypescriptJavaScript 超集,可以给我们的项目代码提供静态类型检查,避免因为各种原因而未及时发现的代码错误,在编译时就能发现隐藏的代码隐患,从而提高代码质量。

但是,TypeScript 项目的一个常见问题是: 如何验证来自外部源的数据并将验证的数据与 TypeScript 类型联系起来。 即,如何避免后端 API 返回的数据与 Typescript 类型定义不一致导致的运行时错误。

Typescript 能用于运行时校验数据类型,那么有没有一种方法,能让我们在 运行时 也进行 Typescript 数据类型校验呢?

io-ts 解决方案?

业界开源了一个运行时校验的工具库:io-ts

//  io-ts 例子
import * as t from 'io-ts'

// ts 定义
interface Category {
  name: string
  categories: Array<Category>
}

// 对应上述ts定义的 io-ts 实现
const Category: t.Type<Category> = t.recursion('Category', () =>
  t.type({
    name: t.string,
    categories: t.array(Category)
  })
)

但是,如上面的代码所示,这工具看起来就有点啰嗦有点难用,对代码的侵入性非常强,要全盘依据它的语法来重写代码。这对于一个团队来说,存在一定的迁移成本。