TypeScript 是 JavaScript 的超集,编译时擦除类型仅留 JS,故 tsc 输出可运行;any 绕过检查,unknown 需守卫;interface 支持声明合并、implements,type 支持联合/元组;严格配置与 CI 校验是类型系统生效前提。

TypeScript 不是 JavaScript 的替代品,而是它的超集——所有合法的 JavaScript 代码都是合法的 TypeScript 代码,但反过来不成立。它在编译期加入类型系统和工具增强,帮你提前发现大量运行时才暴露的问题。
为什么 tsc 编译后生成的 JS 还能正常运行?
TypeScript 的核心设计原则是“零运行时开销”:所有 type、interface、generic 类型标注都在编译阶段被擦除,只留下纯 JavaScript。这意味着:
-
tsc不是转译器(如 Babel),它默认不做语法降级(除非配置target) - 类型错误不会阻止编译(除非启用
noEmitOnError: true),默认仍会输出 JS 文件 - 你写的
const foo: string = 42会被报错,但即使忽略它,生成的 JS 仍是const foo = 42
any 和 unknown 的区别不只是“更严格”
这是初学者最容易误用的两个类型。它们的关键差异在于“是否允许未经检查的操作”:
-
any:绕过所有类型检查,可随意调用方法、访问属性、赋值给任意类型——相当于关闭该变量的 TS 检查 -
unknown:必须显式类型守卫(如typeof、instanceof或类型断言)才能使用,强制你处理不确定性
let a: any = getData();
a.toFixed(); // ✅ 允许,无检查
let b: unknown = getData();
b.toFixed(); // ❌ 报错:Object is of type 'unknown'
if (typeof b === 'number') {
b.toFixed(); // ✅ 守卫后允许
}
接口 interface 和类型别名 type 在什么场景下不能互换?
多数情况下二者等价,但有三个关键不可替代点:
立即学习“Java免费学习笔记(深入)”;
- 声明合并(declaration merging)只支持
interface:interface User { name: string; }和另一个同名interface User { age: number; }会自动合并为{ name: string; age: number; };type不行 -
type可定义联合/元组/映射类型(如type A = string | number),interface不能直接表达联合 - 类实现(
implements)只接受interface,不接受type(除非是对象类型别名且无联合)
类型系统不是银弹。过度泛型、滥用 as any、忽视 strictNullChecks 默认关闭的项目,会让 TypeScript 退化成带类型注释的 JavaScript。真正起效的前提,是团队对 tsconfig.json 中 strict 系列开关达成共识,并坚持在 CI 中校验 tsc --noEmit 退出码。











