TypeScript 入门:从 JS 到 TS 的类型之旅
JS 的灵活是双刃剑:写起来快,改起来怕。TypeScript 把「怕」变成了「编译器替你盯着」。
TypeScript 是什么
TypeScript = JavaScript + 静态类型系统。它不是新语言,是 JS 的超集:所有合法 JS 都是合法 TS,在此基础上加了类型标注。TS 代码不能直接运行,先编译(更准确地叫「转译」)成纯 JS——所以浏览器和 Node 跑的还是 JS,TS 是「开发时的守护层」。
它的价值一句话说透:把运行时才会炸的错误,提前到写代码的那一刻报出来。
function formatDate(date: Date): string {
return date.toISOString();
}
formatDate(new Date()); // ✅
formatDate("2026-01-01"); // ❌ 编译报错:参数需要 Date,给了 string
纯 JS 里第二行要等页面真跑到那一步才抛 date.toISOString is not a function,还得查半天堆栈。TS 在你保存文件的瞬间就画了红线。
基础类型标注
// 基本类型
let title: string = "标题";
let count: number = 42;
let published: boolean = true;
// 数组与对象
let tags: string[] = ["java", "vue"];
let post: { id: number; title: string } = { id: 1, title: "Hi" };
// 函数:参数与返回值
function sum(a: number, b: number): number {
return a + b;
}
// 联合类型:几种取值之一
let status: "draft" | "published" | "deleted" = "draft";
// 可选属性与可能为空
interface Article {
id: number;
summary?: string; // 可能没有
cover: string | null; // 明确可能为 null
}
interface / type 定义结构契约,是 TS 最重要的组织手段:
interface Article {
id: number;
title: string;
tags: string[];
}
function render(a: Article) { /* 用 a.title 一定存在,编辑器有完整提示 */ }
为什么企业项目都上 TS
第一,重构敢下手了。 改一个字段名,所有引用处立刻报错,改完编译通过就是真的改完了——纯 JS 项目里「全局替换字段名」是高风险动作,总有漏网的字符串引用在运行时才爆。
第二,编辑器变成说明书。 拿到一个后端接口返回的对象,鼠标悬停就能看到完整结构;补全提示精确到字段。这比翻文档、console.log 探测快一个数量级。
第三,多人协作的契约。 接口类型定义就是最精确的文档,而且永远不会过时——过时的类型会编译报错,过时的文档不会。
本站前端是 Astro + Svelte + Vue 的混合栈,clarity-api.ts 里定义了几十个接口类型(ArticleDetail、WikiCatalog……),后台返回结构一变,编译立刻告诉你哪些页面会受影响。
渐进式迁移:TS 的友好之处
TS 不要求一步到位。存量 JS 项目可以:
any先兜底——没写类型的变量可以先用any(TS 会放行),后续逐个补类型;allowJs: true——JS 和 TS 文件混存,改哪个迁哪个;- 严格程度可调——
tsconfig.json里strict: false起步,团队适应后逐项打开。
新项目则建议 strict: true 直接开局,最严格的检查从第一行代码就生效。
三个容易踩的坑
any 是逃生门也是黑洞。任何值都能赋给 any,any 也能赋给任何值——用它就等于这一处退回了纯 JS。拿不准类型时优先用 unknown(用前必须收窄,更安全)。
类型是编译期的,运行时不存在。TS 编译成 JS 后类型信息全部擦除,接口返回的数据不会因为你标了 Article 就真的符合结构。边界处要校验:后端返回、localStorage 读出、URL 参数解析,这些入口的数据该手动检查还是得检查。
类型体操要克制。TS 的类型系统图灵完备,能写出几百行的条件类型推理——但可读性归零。业务代码里,简单直接的 interface + 少量联合类型覆盖 95% 的场景。
小结
TS 的本质是把「约定」从人脑和口头搬进了编译器:函数的参数结构、接口的返回形状、状态的合法取值,都变成机器强制的契约。学习路径也简单——先把 interface、基本标注、联合类型用熟,日常开发就够用;泛型、条件类型这些进阶内容,等真实需求来了再学。