前端转全栈笔记:讲框架之前,先把 TypeScript 这关过了

系列专栏:「前端转全栈 · Agent 研发实践」第二章 后续会讲 NestJS 还有中间件的概念,在此之前我们先来回顾一下 TypeScript,主要是熟悉下装饰器的语法,为后续理解 NestJS 做好准备

上一期聊了 Node.js 的核心机制,按路线图接下来该进框架了。但实际学下来我发现中间卡着一关:TypeScript。第一次打开 NestJS 代码时人是懵的——装饰器、依赖注入、constructor 里奇怪的 private,扑面而来的 Java 味儿,用的全是 TS 里我们"知道但不用"的那一半能力。

为什么偏偏在这个时间点要认真复习 TS?因为我越来越强烈地感受到:TypeScript 是 AI Coding 时代的一等公民。

现在我们写代码的方式变了:大量代码由 AI 生成,人负责描述意图和验收。这个协作里,类型就是人和 AI 之间最精确的契约——你给一个函数标清了入参出参,AI 生成的实现就歪不到哪去;项目里类型覆盖越完整,AI 拿到的上下文就越准确,生成的代码一次通过率越高。反过来,满屏 any 的项目,AI 也只能跟着瞎猜。类型系统是 AI 时代少数"人写得越认真、机器干得越漂亮"的基建。

所以这篇我把 TS 完整复习了一遍,按「概念 → 代码 → 坑」整理成两大部分:前半篇复习基础语法(每天真用的那些),后半篇讲为框架打底的三块能力:class、依赖注入这个设计模式、以及装饰器。

TS 的类型在编译后会被全部擦除,运行时一点都不剩。

记住这一句,后面所有的"为什么要这样设计"就都有答案了。

TS 本质是给 JS 加了一层编译期的检查脚手架。tsc 编译完,类型注解、接口、as 断言全部消失,产物就是纯 JS。

TS 的推断很强,能推断就不写。但三个地方要显式写:函数返回值、复杂对象、空数组([] 会被推断成 any[],之后 push 什么都不检查)。

这是 strictNullChecks 的核心价值:逼你把"可能为空"写进类型里,让 Cannot read properties of undefined 这类线上事故在编译期现形。新项目 strict 没有任何理由不开。

坑:push 不受元组长度限制(pair.push('x') 编译不报错)——元组只保证"读取和解构时"的类型,这是 TS 已知的类型不健全点,别让 AI 生成的代码依赖元组的长度安全。

坑:对象字面量直接传参会触发多余属性检查(excess property check);先赋给变量再传就跳过了——拼错的字段会被悄悄忽略:

坑:age?: number 和 age: number | undefined 不等价——前者可以不传,后者必须传一个 undefined。定义回调签名时这个区别经常遇见问题。

后面所有的类型收窄、判别字段(discriminated union)都建立在联合类型上,务必熟练。

纪律:能用收窄解决就不用 as;as unknown as X 双重断言基本等于作弊,Code Review 应当拦下。AI 生成的代码里 as 出现频率偏高,验收时重点扫这个关键字。

标了 any 的变量,能装任何值、能赋给任何人、能调任何方法——类型检查对它完全关闭。所以 any 的真正危害不是"不检查",是会传染:

data 流向的每一处,类型检查全部失效,错误被推迟到运行时。而且一个 any 标记,会让 AI 拿到的上下文在这一片全部失真——这是 AI Coding 时代 any 的新代价。团队里建议直接用 ESLint 的 @typescript-eslint/no-explicit-any 禁掉。

它和 any 一样能装任何值,但反过来:你不能把它直接赋给别人,也不能直接调它的方法——想用,先收窄:

实战规则:API 响应、JSON.parse、catch 的 error(开了 useUnknownInCatchVariables 之后默认就是 unknown),一律标 unknown,逼自己走一遍收窄。多花两行代码,换类型检查重新上岗,值。

它是所有类型的子类型——能赋给任何类型,但没有任何值能赋给它。日常用到它的场景有两个:一是给"永不返回"的函数(抛错、死循环)当返回类型;二是穷举检查:

所有分支都处理完,能走到 default 的 s 理论上"不存在",标成 never 让编译器帮你守着;哪天 Status 加了新成员,这行立刻编译报错,提醒你回来补分支。

先说相同点:都能描述对象结构、都能描述函数、都能被扩展。光看这些会觉得它俩可以互换——确实大量场景能互换,真正的区别藏在下面三点。

interface 只能描述"对象结构";type 是类型别名,什么类型都能起名字——联合、元组、函数、基本类型都行:

区别二:interface 会声明合并,type 不会。

来源:稀土掘金 原文