TypeScript 从零开始详细教程(与 JavaScript 衔接)
前面我们学了 JavaScript 的全部基础,还做了项目。这一篇学 TypeScript(简称 TS)——它是 JavaScript 的”进化版”,目前几乎所有大型前端项目都在用。而且 Vue、React 的官方文档现在都默认用 TS 示例,学完它,你的技能就完整了。
一、TypeScript 是什么?和 JS 什么关系?
一句话:TypeScript 是 JavaScript 的超集——在 JS 的基础上加了”类型系统”。
用一张图理解:
JavaScript 全部代码 ↑ 兼容(TS 里能写 JS)TypeScript = JavaScript + 类型核心区别:
| JavaScript | TypeScript | |
|---|---|---|
| 类型检查 | 运行时才报错 | 写代码时就报错 |
| 常见错误 | 运行时才发现,可能影响用户 | 编译时(开发时)就发现 |
| 谁在跑 | 浏览器直接执行 | 要先编译成 JS,再交给浏览器 |
TS 最大的价值:把错误挡在”写代码的时候”。
看个例子——JS 的经典坑:
// JavaScript:这段代码不会报错,但结果不对function add(a, b) { return a + b;}
console.log(add(1, 2)); // 3,正常console.log(add("1", 2)); // "12"!字符串拼接了,不是加法!JS 不知道你想让 a、b 是数字,传字符串也”乐意”。TS 能在你传错类型时直接画红线:
// TypeScript:声明 a、b 必须是数字function add(a: number, b: number): number { return a + b;}
// add("1", 2); // ❌ 编辑器立刻标红:类型"string"不能赋给"number"console.log(add(1, 2)); // ✅ 3类型是给开发者看的”说明书”,也是让代码更可靠的”安全网”。
二、怎么安装和运行 TypeScript?
安装(需要 Node.js)
npm install -g typescript编译运行
TS 文件后缀是 .ts。写好后用 tsc 编译成 .js:
# 1. 写一个 hello.ts 文件# 2. 编译tsc hello.ts# 3. 生成了 hello.js,再用 node 运行node hello.js每次都要编译太麻烦? 用 watch 模式,文件一保存自动编译:
tsc --watch hello.ts直接在浏览器控制台试(不装也能玩)
TypeScript 官方提供了在线练习场:访问 TypeScript Playground(tsplay.dev),左边写 TS 右边看编译后的 JS,零安装就能学。学习阶段强烈推荐先用它。
三、基础类型:给数据”贴上标签”
TS 的写法就是在变量后面加 : 类型。
原始类型
let age: number = 18; // 数字let price: number = 3.14; // 小数也是 numberlet name: string = "小明"; // 字符串let isDone: boolean = true; // 布尔
// null 和 undefinedlet empty: null = null;let notSet: undefined = undefined;数组
let numbers: number[] = [1, 2, 3]; // 数字数组let names: string[] = ["小明", "小红"]; // 字符串数组// 或者用泛型写法(等价)let nums: Array<number> = [1, 2, 3];元组(Tuple):固定长度和类型
let person: [string, number] = ["小明", 18];// person = [18, "小明"]; // ❌ 错误:顺序不对any 和 unknown:特殊情况
let anything: any = 42; // any:任何类型都行(尽量少用,会失去 TS 的保护)anything = "字符串也可以";
let maybe: unknown = "某个未知值"; // unknown:类型未知(比 any 安全)原则: 能用具体类型就用具体类型;any 会让 TS 失去意义,尽量别用。
类型推断:不写也能自动识别
TS 很聪明,初始化时就能自动推断类型,不写也行:
let age = 18; // TS 自动推断 age 是 number// age = "十八"; // ❌ 报错:不能把 string 赋给 number建议: 简单变量靠推断,函数参数和返回值主动写清楚。
四、接口(interface):给对象”定规矩”
对象是 JS 里最常用的数据结构。TS 用 interface 规定”对象必须长什么样”:
interface Student { name: string; age: number; grade?: string; // ? 表示可选,可以没有}
// 符合接口的对象let s1: Student = { name: "小明", age: 18 };let s2: Student = { name: "小红", age: 17, grade: "高二" };
// let s3: Student = { name: "小刚" };// ❌ 报错:缺少属性 age为什么有用? 团队协作时,接口就是”契约”:写数据的人知道要提供什么,用数据的人知道有什么字段。IDE 还会自动提示字段名,防止拼错。
接口也可以描述函数
interface AddFn { (a: number, b: number): number;}
const add: AddFn = (a, b) => a + b;接口可以被”继承”(extends)
interface Person { name: string; age: number;}
interface Employee extends Person { company: string; // 在 Person 基础上再加字段}
let e: Employee = { name: "张三", age: 30, company: "某公司" };五、类型别名(type):给类型起外号
type 可以给类型起别名,还能定义一些 interface 做不到的(比如联合类型):
// 给对象类型起别名type Point = { x: number; y: number;};
// 给联合类型起别名type Status = "pending" | "success" | "error"; // 只能是这三个字符串之一
let s: Status = "success"; // ✅// let s2: Status = "failed"; // ❌ 不在列表里联合类型(Union):一个值可以是多种类型
// id 可以是数字或字符串function getById(id: number | string) { console.log("查询 id:", id);}
getById(1); // ✅getById("abc"); // ✅交叉类型(Intersection):合并多个类型
type Name = { name: string };type Age = { age: number };
type Person = Name & Age; // 两个都要有
let p: Person = { name: "小明", age: 18 }; // ✅六、函数类型:参数和返回值都要”说清楚”
基本写法
// 参数类型 + 返回值类型function greet(name: string): string { return `你好,${name}`;}
// 箭头函数也一样const add = (a: number, b: number): number => a + b;可选参数
function register(name: string, phone?: string) { console.log(`注册用户:${name}`); if (phone) { console.log(`手机号:${phone}`); }}
register("小明"); // ✅ 不传 phone 也行register("小红", "13800000000"); // ✅注意: 可选参数必须放在最后面。
默认参数
function discount(price: number, rate: number = 0.9) { return price * rate;}
discount(100); // 90(用默认 0.9)discount(100, 0.5); // 50void:没有返回值的函数
function log(message: string): void { console.log(message); // 没有 return}七、类(class)与访问修饰符
TS 的类在 JS 的 class 基础上加了类型和访问控制:
class Animal { // 属性要先声明类型 name: string; private age: number; // private:只有类内部能访问
constructor(name: string, age: number) { this.name = name; this.age = age; }
speak(): void { console.log(`${this.name} 叫了一声`); }
getAge(): number { return this.age; }}
let dog = new Animal("旺财", 3);dog.speak(); // 旺财 叫了一声console.log(dog.name); // ✅ 公开属性可以访问// console.log(dog.age); // ❌ private 属性外部访问不了修饰符速记:
public(默认):谁都行private:只有类内部protected:类内部和子类
八、泛型(Generic):写一次,多种类型通用
泛型让你的函数/类”不写死类型”,用的时候再定。最经典的例子是数组反转:
// 不用泛型:只能处理数字function reverseNum(arr: number[]): number[] { return arr.slice().reverse();}
// 用泛型:任何类型都能处理function reverse<T>(arr: T[]): T[] { return arr.slice().reverse();}
reverse([1, 2, 3]); // number[],T = numberreverse(["a", "b", "c"]); // string[],T = string<T> 里的 T 是一个”类型变量”,调用时自动推断成实际类型。好处: 一种逻辑,各种类型通用,而且类型检查不会丢。
另一个常见例子:
function firstElement<T>(arr: T[]): T | undefined { return arr[0];}
let first = firstElement([10, 20, 30]); // first 的类型是 number九、tsconfig.json:TS 项目的”总配置”
真实项目里,TS 的编译配置放在 tsconfig.json 里。用命令一键生成:
tsc --init生成的配置里,最常用的是这几项:
{ "compilerOptions": { "target": "ES2020", // 编译成哪个版本的 JS "module": "ESNext", // 模块系统 "strict": true, // 严格模式(强烈建议开启) "outDir": "./dist", // 编译输出目录 "rootDir": "./src" // 源码目录 }, "include": ["src"] // 编译哪些目录}"strict": true 最重要——它开启所有严格检查(包括 null 检查),虽然刚开始会觉得”烦”,但它能拦住大量真实 bug。业界共识:新项目一定要开 strict。
十、从 JS 平滑过渡到 TS 的路线
如果你已经把前面的 JS 教程学完,过渡到 TS 其实非常自然:
| JS 写法 | TS 写法 | 变化 |
|---|---|---|
let age = 18 | let age: number = 18 | 加类型(也可靠推断不写) |
function f(a, b) | function f(a: number, b: number): number | 参数和返回值加类型 |
const obj = {...} | interface X {...} + 类型标注 | 用接口定义对象形状 |
const add = (a,b) => a+b | const add = (a: number, b: number) => a + b | 箭头函数加类型 |
三个实用技巧:
- 遇到报错先看类型:TS 报错信息会把原因说得很清楚(“不能把 string 赋给 number”),跟着改就行
- 用
?处理可能为空的字段:user?.name可选的配合?.可选链,避开”读不到属性”错误 - 不确定就用
unknown加类型收窄:用typeof或instanceof判断后再操作
function process(value: unknown) { if (typeof value === "string") { console.log(value.toUpperCase()); // 收窄后 TS 知道它是 string } else if (typeof value === "number") { console.log(value + 1); }}实际项目怎么用? 现在的主流做法:
- Vue 3 项目:
<script setup lang="ts">,组合式 API 天然支持类型 - React 项目:函数组件参数用接口描述 props
十一、总结
这一篇我们从零学完了 TypeScript:
- TS 是 JS 的超集:加类型系统,把错误挡在开发时
- 安装运行:tsc 编译,Playground 在线练习
- 基础类型:number、string、boolean、数组、元组、any、unknown
- 接口 interface:给对象”定规矩”,支持继承
- 类型别名 type:联合类型、交叉类型
- 函数类型:参数、返回值、可选参数、默认参数、void
- 类与修饰符:public、private、protected
- 泛型:写一次、多种类型通用
- tsconfig.json:项目配置,strict 必开
- 过渡路线:JS 写法 + 类型标注 = TS
到这里,你的前端学习主线就完整了:
JavaScript 基础 → ES6+ → 异步编程 → fetch 网络请求 → HTML/CSS 强化 → Vue/React 框架 → 项目实战 → TypeScript
接下来就是不断做项目、读源码、写代码。编程是门手艺,手艺靠练不靠看。 把教程里的每个示例都亲手敲一遍,你就真正入门了。加油!