Go 语言几乎打了所有 Programming Language 学者的脸,然而它却成功了,为什么?

发布时间:
2025-03-18 23:12
阅读量:
2

你以为打的是 PL 学者的脸,其实打的是 JS/TC39 和 TS 自己的脸:ts 仓库源码近似于 C with gc 的代码风格,甚至可以一比一复刻 (porting) 到 go,可以说是臭写 TS 的操弄着类型体操,最后编译出 php 的性能 —— 只有 ts-go 版的

为什么 TypeScript 的 checker.ts 文件如此之长?
  1. 不用 try-catch、没有类、没有 proxy 反射、没有任何其他动态特性,完全基于一些基础的 interface 构造 + 各种工具函数来实现,源码很好看懂,完全 0 门槛
  2. 全 if-else 风格,没有任何 obj[key] 表驱动写法,拒绝动态化 / 反射 (提一个点 transformer pipeline 居然是通过套闭包函数的方式来做的,不会存到数组上 )
  3. 无模式匹配,所有 AST / Token type 统一全用基于 const enum 的数字,引入一系列 isXXX 谓语
  4. 为了避免 js 的点读开销,直接将所有类型检查逻辑 all-in-one 在一个 5 万行的 checker.ts 里
    而又因为文件太长,let 的 TDZ check 的开销都不可忽略,因此 prefer to use var 来声明变量

这种类 C with GC 的代码风格除了 golang 找不到更合适的了; 换其他语言基本要推倒重做。

上述的这些性能问题,尤其打包,TS 完全可以继续迭代 namesapce 特性做自己的静态化 all-in-one js 的打包方案来解决。

(其实 TS 也做过 all-in-one 打包,TS4.x 以前 outFile 是填成一个文件而不是目录,此时构建后代码在一个文件内,基于 namespace 的模块化是面向仓库里的 tsconfig.json 而不是文件 A import B 的点对点,扯远了)


但是目前 TS 自己又不断强调不做 runtime 效果因此 TS 自己对自己的实现及其拧巴,尤其 5.x 之后放弃了在源码里使用 namespace 后,目前的实现可以说是龌龊,比如下面的 ts.ts 用 ESM 去模拟 namespace:

牛逼, https://github.com/microsoft/TypeScript/blob/main/src/jsTyping/_namespaces/ts.ts#L1

—— TS 的这些 runtime 的特性其实社区用的非常多,除了 enum 外,namespace JSX 几乎是整个 React / Vue TSX 生态的基础,但是官方对这些特性又持有一种微妙的态度,我估计 TS Core Team 内部也是分歧相当大的,比如 RyanCavanaugh 老哥认为 const-enum 是个 mistakes:

https://github.com/microsoft/TypeScript/issues/30590

虽然他认为这是 mistake 但是 ts 其源码自身为了性能又无限制使用 const-enum / downlevelIteration / namespace 这些特性,上面这段真是让人忍俊不禁 (虽然这些 runtime feature 虽然很薄,但总比没有好)

最后暴论一下: 我原以为 TS 的性能问题很可能促使 TS 去做基于静态类型的 codegen 优化,比如 moonbit 的 js 后端那样输出优化后的 js0 源码,terser 这类 for js 设计的 tree-shaking / inline 等等,但我没想到最后换 ts-go 来解决了,因此从这个角度来看 ts 后面不会有大的演进了,换成 ts-go 也不过是编译快一些,语言自身倒是没咋变,后续演进可以算是一眼望到头。

目前 TS 的类型体操已经足够完备覆盖绝绝绝大部分场景,zhihu 上有不少这方面内容,什么 parser / 虚拟机 / lisp 啥都能做,我甚至在想,把 type 那部份编译成 wasm 搞不好比 js/ts 还要快,总之再开发新的 types 也只是服务于一些小众场景而已,边际效应已相当明显

最后给个结论:一个类型体操极其牛逼的、高速发展了十年的超明星级编程语言,2025 了居然不支持常量合并这种基础的 PL 效果,过于抽象
(感觉确实是打脸了 PL 学者,堪比 2025 的 npm 还不支持 package.json 注释,go 那点 shit 还得让让)

const a = 1 + 1; // 什么时候 ts 将其编译为 const a = 2; 才能说这语言有自己的未来 // ( 对于看过源码的我来说,这个其实在 const enum 的 codegen 那块差不多实现了。。。 // 只是没有实现加法,总之垃圾 ts 毁我青春 )

TS 已死

END