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 在 20052008 年谈 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 typingJavaScript data types and data structuresJavaScript 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 HejlsbergTypeScript 的核心发起者。理解为什么后来能切进 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