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”,同时又一直处理不好边界,绕不开他。

参考与延伸阅读

  1. Dynamic typing - MDN
    https://developer.mozilla.org/en-US/docs/Glossary/Dynamic_typing

  2. JavaScript data types and data structures - MDN
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures

  3. JavaScript language overview - MDN
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Language_overview

  4. Why does TypeScript exist?
    https://www.typescriptlang.org/why-create-typescript/

  5. TypeScript for the New Programmer
    https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html

  6. JavaScript 1, 2, and in between - Brendan Eich
    https://brendaneich.com/2005/06/javascript-1-2-and-in-between/

  7. JavaScript creator ponders past, future - InfoWorld
    https://www.infoworld.com/article/2653798/javascript-creator-ponders-past-future.html

  8. ECMAScript 4th Edition - Language Overview
    https://archives.ecma-international.org/2007/misc/overview.pdf

  9. JS2 Design Notes - Brendan Eich
    https://brendaneich.com/2005/11/js2-design-notes/

  10. TypeScript Design Goals
    https://github.com/microsoft/TypeScript/wiki/TypeScript-Design-Goals