01|今天很多人觉得 TypeScript 很自然,可在很长一段时间里,“给 JavaScript 加类型”这句话听起来其实非常不对劲
如果你今天才进入前端,很容易产生一种错觉:
- 大项目上
TypeScript很正常 - 编辑器里有类型提示很正常
- 组件库带类型声明很正常
- 招聘里要求
TS也很正常
于是再回头看,会很自然地以为:
JavaScript 世界迟早都会走向类型。
可如果你把时间线往前拉,这个判断其实并不成立。
因为在很长一段时间里,
“给 JavaScript 加类型”在很多人听来,不像升级,
更像是:
- 把简单事情搞复杂
- 把灵活语言往重语言那里拽
- 把一门脚本语言改得越来越不像脚本语言
所以第一篇最重要的起点不是:
“类型到底好不好。”
而是更前面那个问题:
为什么 JavaScript 社区会长期本能地对类型这件事带着防备,甚至带着一点反感?
因为如果这个问题不先讲清楚,
后面你就很容易把 TypeScript 的崛起误写成一种线性进步:
好像大家只是终于看明白了“静态类型更高级”。
真实历史不是这样。
真实历史更像是:
JavaScript 一开始就不是按“强秩序语言”那条路被发明、被传播、被喜爱的。
它最早被喜欢上的,恰恰是另一套东西。
02|因为 JavaScript 最初被交到 Web 世界手里时,根本不是按“严肃大型语言”那种气质定位的
这件事特别关键。
JavaScript 最初面对的,不是“我们要给大型应用找一种更可验证的语言”。
它最初面对的是:
网页作者能不能直接在页面里写一点脚本,让页面活起来。
这会带来一整套非常不同的设计倾向。
因为当时真正重要的不是:
- 类型系统够不够严密
- 编译期约束够不够强
- 大型代码库治理是否完善
而是:
- 能不能直接嵌进浏览器
- 能不能让更多网页作者快速上手
- 能不能写一点小脚本就看到效果
- 能不能别像 Java 那样有很强的仪式感
这就决定了 JavaScript 从第一天起最先被强调的,不是“先声明清楚,再开始写”。
而是:
先写起来。
从这个起点出发,语言气质当然会更偏向:
- 轻
- 快
- 灵活
- 容错
- 低门槛
而不会先偏向:
- 严格边界
- 显式约束
- 提前建模
- 用类型先把世界定义好
所以 JavaScript 世界后来长期对类型天然警惕,
并不只是因为社区“落后”。
更大的原因是:
这门语言最初建立声望的地方,本来就不是秩序感,而是低摩擦。
03|动态类型在 JavaScript 早期不是缺点暴露,而是它“够好用”的一部分
MDN 到今天都还把 JavaScript 明确描述为动态类型语言:
变量不需要在声明时指定类型,
同一个变量可以在运行过程中被重新赋成不同类型的值。
这件事放到今天的大型工程语境里,大家第一反应往往是风险:
- 容易出错
- 难以重构
- 难以预判边界
可你如果把它放回早期 Web 的现实里,这套特性最先呈现出来的反而是好处:
- 上手快
- 写得快
- 改得快
- 不需要先理解太多制度
比如你在页面里写一点表单校验、小按钮逻辑、DOM 操作,
你最需要的常常不是“先把这份数据的结构完整描述清楚”。
你更常需要的是:
我先把这段交互写出来,看它能不能动。
这就是 JavaScript 早期最强的一种现实吸引力。
它让开发者先从“行为”出发,
而不是先从“类型边界”出发。
所以动态类型在那个阶段并不只是“历史局限”。
它也是 JavaScript 当时作为网页脚本语言能快速扩散的重要原因之一。
04|久而久之,这种低摩擦写法不只是语法特征,还会慢慢长成一种社区性格
这一步很容易被忽略。
很多人讲语言史时,只讲规范和特性。
可一门语言真正稳定下来之后,真正会影响后续路线的,往往还有它逐渐形成的社区自我认同。
JavaScript 的这套自我认同里,很早就有几层特别强的东西:
第一层是:
别把写页面这件事弄得太重。
第二层是:
别让一门本来适合快速拼装的语言,变得越来越像企业级重型语言。
第三层是:
运行时自由和表达灵活,本来就是这门语言的一部分。
这就意味着,后来每当有人试图往 JavaScript 世界里引入更多“提前声明、提前校验、提前规定边界”的东西,
很多开发者的第一反应都不会是欢迎。
而会是怀疑:
- 这是在解决真实问题,还是在引入新的仪式负担
- 这是在帮 JavaScript,还是在把 JavaScript 改造成另一门语言
- 这是在增强表达,还是在限制原本的灵活性
所以“反感类型”在 JavaScript 世界里,很多时候并不是单点技术判断。
它更像一种语言本能。
05|这也是为什么 JavaScript 世界早期更习惯把问题留给运行时、测试、约定和经验,而不是优先交给类型系统
如果一门语言的默认文化是“先写起来”,
那它遇到复杂度时,最先长出来的缓冲办法,通常也不会是正式类型制度。
JavaScript 世界更常见的早期办法是:
- 运行时判断
- 文档注释
- 命名约定
- 单元测试
- 团队习惯
这不是说这些办法一定更好。
而是说:
它们更符合 JavaScript 世界原本的行动方式。
因为这类办法大多有一个共同点:
它们不要求你在写代码之前,就先把整个世界建模完。
它们更像是在说:
- 先让代码活着
- 再慢慢补约束
- 哪里出问题,哪里补规则
这套思路和很多静态类型语言背后的直觉并不一样。
后者更像是在强调:
你最好先把边界说清楚,再放心让系统变大。
而 JavaScript 世界长期更熟悉的是另一种节奏:
先把系统跑起来,再逐步想办法别让它失控。
也正因为如此,类型系统在这个世界里,天然就更像一种“额外制度”,
而不是从第一天起就被当成默认空气。
06|但这不等于 JavaScript 世界真的完全不想要秩序,它更准确的心态其实是:我可以要秩序,但你别把我改成 Java
这一点如果讲不准,第一篇就会失真。
因为 JavaScript 世界并不是从来没有人想过“programming in the large”。
恰恰相反。
随着 Ajax、DHTML、富交互页面和大型前端代码慢慢长起来,
很多人很早就已经意识到:
JavaScript 如果继续只靠“小脚本语言”的老办法硬撑,迟早会出问题。
这也是为什么 ES4 / JS2 那条线里,其实已经认真讨论过:
- 类
- 模块
- 命名空间
- 可选类型标注
- 面向大型程序的约束能力
Brendan Eich 在 2005 和 2008 年谈 JavaScript 未来时,一边明确说过:
JS does not need to become Java, or C#, or any other language.
另一边又同时承认:
JavaScript 已经不再只是“小片段语言”,它也开始面对大型程序的问题,需要某种关于模块、接口和类型的能力。
这说明什么?
说明 JavaScript 社区真正长期抗拒的,
很多时候并不是一切秩序。
它更抗拒的是:
那种会让 JavaScript 失去自己语言身份的秩序。
换句话说,这个世界不是完全不要规则。
它要的是:
- 规则最好别太重
- 约束最好别破坏运行时现实
- 新制度最好别把旧代码一把推翻
- 秩序最好是渐进接入,而不是全面改朝换代
这会直接决定后面 TypeScript 能不能活下来。
07|所以 TypeScript 后来真正聪明的地方,第一步不是“把类型做强”,而是先看懂了 JavaScript 世界到底讨厌什么
这是整套系列后面必须一路记住的前提。
如果你站在一个完全外部的视角,
你会很容易得出一种简单方案:
“既然 JavaScript 规模变大了,那就直接给它上一套更严格、更强、更完整的类型体系。”
可问题在于,
JavaScript 世界早就已经告诉你它最敏感的那几条红线是什么:
- 别破坏现有 JavaScript
- 别强迫所有人一次性重写
- 别把运行时搞成另一套东西
- 别让开发门槛一下抬太高
而 TypeScript 后来之所以能切进来,
恰恰是因为它没有和这些红线硬碰硬。
官方文档后来把这件事说得非常明确:
TypeScript是 JavaScript 的 superset- 目标之一是保留所有 JavaScript 代码的运行时行为
- 类型系统是可擦除的,不给运行时增加额外负担
这其实已经是在正面回应 JavaScript 世界最深的那份历史脾气。
所以第一篇如果只看“JavaScript 为什么排斥类型”,
你会觉得这是一篇讲阻力的文章。
可它真正更重要的作用其实是:
解释为什么后来能赢下来的那套方案,必须长得不像对 JavaScript 的正面征服,而更像对它语言习惯的一次谨慎收编。
08|为什么 JavaScript 真正抗拒的,从来不只是类型
把前面几层叠一起看,第一篇最重要的判断可以压成一句:
JavaScript 社区长期本能地排斥的,不只是类型本身,而是任何会威胁它“低摩擦脚本语言”身份的东西。
这句话里有几层意思。
第一,JavaScript 最初赢的不是严密性,而是低门槛和灵活度。
第二,动态类型在早期 Web 现实里并不只是问题,它也是扩散能力的一部分。
第三,后来社区真正抗拒的,很多时候不是秩序本身,而是“让 JavaScript 变得不像 JavaScript”的秩序。
第四,这种历史形成的语言气质,会反过来决定所有后来者必须怎么和它打交道。
所以理解 TypeScript 的第一步,不该从“类型系统有多强”开始。
更该从这里开始:
JavaScript 为什么会对类型这件事本能地先皱眉。
09|JavaScript 早期抗拒的,是被静态制度先框起来
TypeScript 江湖 的第一篇,最值得记住的,不是“JavaScript 社区曾经不懂类型”这种轻浮判断。
更值得记住的是:
JavaScript 长期对类型天然警惕,是因为这门语言从诞生起就更强调低门槛、快速上手、运行时灵活和脚本式表达,而不是先把世界用静态制度框起来。
也正因此,
后来任何想给 JavaScript 带来更多秩序的方案,
都不可能只是“更先进”就够了。
它还必须先回答一个更难的问题:
怎样在不背叛 JavaScript 原始自我认同的前提下,把秩序一点点带进来。
这就是下一篇要正式进入的地方。
因为 TypeScript 真正厉害的第一步,
从来都不是先证明“类型正确”。
而是先证明:
“我不会先把你变成另一门语言。”
编者注(事实核对):文中关于 JavaScript 是动态类型、弱类型语言的描述,主要依据 MDN 对 Dynamic typing、JavaScript data types and data structures 与 JavaScript language overview 的说明,其中明确写到 JavaScript 的类型附着在值而不是变量上,变量可在运行时被重新赋为不同类型。关于 TypeScript 官方如何回看 JavaScript 的原始定位,主要依据 Why does TypeScript exist? 与 TypeScript for the New Programmer,两者都明确把 JavaScript 描述为最初用于网页中少量脚本和简单交互的小语言,后续才被推到大型应用场景。关于 JavaScript 社区并非完全拒绝秩序、而是长期警惕把 JS 改造成 Java / C# 这类重语言,主要依据 Brendan Eich 在 2005 年博客《JavaScript 1, 2, and in between》中“JS does not need to become Java, or C#, or any other language.”的表述,以及 2008 年 InfoWorld 采访中他对“programming in the large”与“不要做成 painfully static”的说明。关于 ES4 / JS2 确实尝试过可选类型、类和模块等“面向大型程序”能力,主要依据 ECMAScript 4th Edition – Language Overview 与 Brendan Eich 的 JS2 Design Notes。正文将这些线索综合概括为“JavaScript 长期排斥的,不只是类型本身,而是任何会威胁它低摩擦脚本语言身份的东西”,属于对语言定位、社区文化和历史方案边界的综合判断。
关键人物速览
- Brendan Eich:JavaScript 的创造者。理解这门语言为什么从一开始就强调脚本式灵活性,以及为什么后来又反复强调“别把 JS 变成 Java”,绕不开他。
- Anders Hejlsberg:
TypeScript的核心发起者。理解为什么后来能切进 JavaScript 世界的方案,必须优先尊重旧世界边界,绕不开他。 - Waldemar Horwat:ES4 / JS2 时期的重要设计者之一。理解 JavaScript 世界为什么很早就想过“programming in the large”,同时又一直处理不好边界,绕不开他。
参考与延伸阅读
Dynamic typing - MDN
https://developer.mozilla.org/en-US/docs/Glossary/Dynamic_typingJavaScript data types and data structures - MDN
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structuresJavaScript language overview - MDN
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Language_overviewWhy does TypeScript exist?
https://www.typescriptlang.org/why-create-typescript/TypeScript for the New Programmer
https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.htmlJavaScript 1, 2, and in between - Brendan Eich
https://brendaneich.com/2005/06/javascript-1-2-and-in-between/JavaScript creator ponders past, future - InfoWorld
https://www.infoworld.com/article/2653798/javascript-creator-ponders-past-future.htmlECMAScript 4th Edition - Language Overview
https://archives.ecma-international.org/2007/misc/overview.pdfJS2 Design Notes - Brendan Eich
https://brendaneich.com/2005/11/js2-design-notes/TypeScript Design Goals
https://github.com/microsoft/TypeScript/wiki/TypeScript-Design-Goals