类型定义即是量纲

2019 年阅读的前端项目终于吃上了 TypeScript,群众纷纷反映真香!

我在思考,类型定义对于程序语言来说究竟算是什么呢?我们大家都知道编译型语言类型检查不通过是会编译失败的,返回一个错误信息,那么我们为什么要保证变量类型呢?
我不想先谈那些内存结构啊,指针之类的,我想说的是类型定义就好比物理学里的“量纲”。

我们会说 1 立方米的木头,1 吨的木头,都是可以的。但我们不会说 1 安培的木头,或者 1 摄氏度的木头。因为这些量纲没法衡量木头的多少,或者说即使确实有 1 安培电流通过的木头,表面温度为 1 摄氏度的木头,我们也没法了解它到底意味着什么(能换多少钱,需要多少辆车才能拉动?)。

计算机程序是简单的,每个变量,每个函数,他们都只会做两件事,那就是被写入内存和从内存读取,量纲是他们在内存里分配的形式,u32i64 就是不同的变量,长得不一样,功能也不一样。

JavaScript 是弱类型的语言,它容忍隐式类型转换。但 TypeScript 不允许这样做。我们不能把 string 类型的变量传给一个接受 number 类型参数的函数,就好像我们没法把木头接到灯泡上指望它发光一样(好吧,如果这是一段带点的木头就当我在放屁),尤其是你接到的还是一段看起来很像电池的木头,比如名为 battery,但类型是 wood

另外,保证量纲被定义的好处是我们拥有了更好的接口提示,即使之前就有 document comment,但我们依然只能通过 description 来辨识变量类型和猜测该用的参数,有 TypeScript 以后 ……

https://juejin.im/post/5d8efeace51d45782b0c1bd6

最后,我想说的是,即使 TypeScript 给开发过程带来了巨大的便利,但我们仍应该清楚地认识到它只是一门 JavaScript 的预处理语言,运行时仍是那个不带类型检查的玩具语言(?),当 API 接口返回的数据不同于类型定义的 Interface 怎么办?

Runtime Type Check

一种方案是 WebAssembly,在 Rust 代码里用 Serde 之类的序列化工具来整理 JSON 数据,如果遇到不存在的属性会直接报错

另一种就是 JS 方式:invariant

1
2
3
4
5
6
7
var invariant = require('invariant');

invariant(someTruthyVal, 'This will not throw');
// No errors

invariant(someFalseyVal, 'This will throw an error with this message');
// Error: Invariant Violation: This will throw an error with this message

评论