全栈开发学习教程

前端 TypeScript + 后端 Python,从零到独立开发全栈应用
全部中文注释 · GSAP 动画讲解 · Remotion 风逐行代码播放器

0
章节
0
交互练习
0
免费资源
0
代码播放器

为什么选 TypeScript + Python?

这是 2025 年独立开发者性价比最高的技术组合

语言框架理由
前端TypeScriptNext.js + React前端世界就这一门语言,TS 是加了类型系统的 JS
后端PythonFastAPI学习曲线最低、AI 生态最强、自动化脚本王者
💡 学习策略

不要同时学两门语言。先学 TypeScript(2-4 周基础),再学 Python(2-4 周基础),最后做全栈项目把两者连起来。每章都有练习和动画播放器,做完再往下走。

⚠️ 前置要求

你需要一台电脑,安装好 Node.js 和 Python:nodejs.orgpython.org

★ 写给完全没碰过代码的你

如果你看到 let name = "小明" 就头大,这一章就是给你写的。先读这章,再开始第 1 节。

一个最大的秘密:编程只是 6 个动作

你看到的所有程序——无论淘宝、抖音、Excel 公式还是 AI——都只是这 6 个动作的不同组合:

动作生活中你在干嘛编程叫什么
① 把一个东西存起来,记住它的名字把客户电话写在笔记本上,标注"张三"变量
按条件决定做不做"如果张三还钱,今天就发货;否则再等等"if 条件
重复做同一件事每天把店里 30 件商品各擦一遍循环
④ 写一份 SOP 标准流程新员工入职,照着"接单流程"做函数
⑤ 把一堆同类的东西排成一列手机里的通讯录清单数组/列表
⑥ 给一份资料贴上标签方便查找客户档案袋上写"姓名/电话/地址"对象/字典
🎯 记住这句话就够了

"程序 = 数据 + 处理步骤"。不管代码多复杂,拆开看就是:先有几个数据(变量/数组/对象),然后告诉电脑怎么处理它们(if/循环/函数)。

6 个动作的可视化(滚动看每个)

📦

① 变量 = 贴了标签的盒子

你给一个盒子贴个标签,盒子里面装一个东西。变量 = 一个盒子,标签 = 名字,里面装的东西 = 值

name
"小明"

代码:name = "小明"

② if 条件 = 现实选择题

你在店里天天做:「如果下雨就关门打烊,否则正常营业」。编程里叫 if / else

下雨了吗?
是 → 关门打烊
否 → 正常营业
🔄

③ 循环 = 流水线机器

你每天早上要把店里 30 件商品各擦一遍——你不会写 30 行"擦商品"代码,而是写一遍"擦商品"的指令,告诉电脑重复 30 次

📱手机 📺电视 💻电脑 🎧耳机

「对这 4 件商品,每件都做"展示价格"」

📋

④ 函数 = SOP 标准作业流程

新员工入职,你给他一张流程单:「输入客户姓名 → 查系统 → 发短信」。这张流程单就是 函数——输入材料(参数),按步骤做,输出结果(返回值)。

① 输入:客户姓名
② 在系统里查
③ 输出:发短信
📝

⑤ 数组/列表 = 通讯录清单

通讯录本质上是一张按顺序排列的清单:第 1 位张三,第 2 位李四,第 3 位王五。代码里叫 数组 / 列表(list)

序号名字电话
0张三138-xxxx
1李四139-xxxx
2王五156-xxxx

代码:contacts = ["张三", "李四", "王五"] 第 1 位是 contacts[0]

🗂️

⑥ 对象/字典 = 档案袋

每个客户有个档案袋,上面贴着"姓名/电话/地址"三张标签,每个标签对应一个值。这叫对象 / 字典(dict)——标签叫"键",内容叫"值"。

姓名张三
电话138-1234
地址广元市

代码:user["电话"] → "138-1234"

🎁 学完整个教程你能干什么?

1
做个小生意展示网站

比如把你家的卤菜、农产品、家宴服务挂到网上,让人能直接下单付款

2
做抖音/小红书爬虫

批量下载竞品视频、采集爆款文案、自动筛选评论

3
做 AI 工具

用 Whisper 把你的视频转字幕、用 GPT 自动写你的产品文案

4
帮人接活

你姐、好友的店要做小程序、要获客——你都能接

👣 接下来怎么走

第 1 章和第 5 章是新手最容易卡住的——里面已经加了「人话翻译」卡片,看到代码先读卡片,再读代码。每段代码最长 5 行,超出 5 行的我都加了拆解说明。别急,慢慢来。

学习路线图

按顺序走,每一步都有明确的产出物。不要跳步。

1

TypeScript 基础(第 1-4 章)

理解类型系统、接口、函数类型、联合类型、泛型。产出:能用 TS 写出带类型的小程序。

2

JavaScript 实战(第 5-7 章)

掌握变量、数组方法、对象解构、async/await。产出:能用 JS 操控 DOM、发请求、处理数据。

3

Python 基础(第 8-11 章)

变量、数据结构、函数、文件操作、面向对象。产出:能用 Python 写脚本和数据处理程序。

4

FastAPI 后端(第 12-13 章)

创建 API、路由参数、Pydantic 验证、CRUD 操作。产出:能跑起一个带文档的后端 API 服务。

5

全栈联调(第 14 章)

前端 TS 调后端 Python API,完成增删改查。产出:一个能跑的全栈 Demo。

1. TypeScript 是什么

TypeScript(简称 TS)是 JavaScript 的超集,简单说就是"加了类型系统的 JavaScript"。你写的 TS 代码最终会被编译成 JS 来运行。

为什么不用纯 JavaScript?

🔍 对比:JS vs TS
JavaScript — 不报错,运行时才发现问题
/* JS 不检查参数类型,传错了运行时才暴露 */
function add(a, b) {
  return a + b;
}
add(1, "2"); /* 返回 "12",不是 3!JS 不会报错 */
TypeScript — 写代码时编辑器直接红线提示
/* TS 在写代码时就告诉你类型对不对 */
function add(a: number, b: number): number {
  return a + b;
}
add(1, "2"); /* ❌ 编辑器直接红线报错!数字+字符串 */
💡 核心价值

TypeScript 的核心价值:在代码运行之前就发现错误。越早发现 bug,修复成本越低。大型项目中用 TS 已是标配。

安装 TypeScript

终端
/* 全局安装 TypeScript 编译器 */
npm install -g typescript

/* 验证安装是否成功 */
tsc --version

第一个 TS 程序

hello.ts
/* 定义一个接口:描述"用户"对象长什么样 */
interface User {
  name: string;
  age: number;
}

/* 函数接收 User 类型参数,返回字符串 */
function greet(user: User): string {
  return `你好,${user.name},你 ${user.age} 岁了`;
}

const me: User = { name: "小明", age: 25 };
console.log(greet(me)); /* 输出:你好,小明,你 25 岁了 */
终端
/* 编译 TS → JS,生成 hello.js */
tsc hello.ts
/* 用 Node.js 运行编译后的 JS */
node hello.js
选择题练习 TS-01
TypeScript 和 JavaScript 的关系是什么?
ATypeScript 是全新语言,和 JS 没关系
BTypeScript 是 JS 的超集,所有合法 JS 都是合法 TS
CTypeScript 将取代 JavaScript
DTypeScript 只能在浏览器中运行

2. 基础类型系统

TypeScript 的核心就是类型标注——告诉编译器每个变量是什么类型。下面用 Remotion 风逐行动画播放器 一步步讲解:

REMOTION STYLE
🎬 逐行讲解 · TypeScript 类型系统
第 1 步
1/0

类型推断

💡 类型推断

其实很多时候你不需要手动写类型。TS 会自动推断:let x = 42 自动推断 x 是 number。只有函数参数、复杂对象等才需要显式标注。

填空题练习 TS-02
补全类型标注,让这个数组只允许存数字:
let scores: = [90, 85, 92];

3. 函数与接口

函数类型

TypeScript
/* 参数和返回值都可以标注类型 */
function add(a: number, b: number): number {
  return a + b;
}

/* 箭头函数也可以加类型 */
const multiply = (a: number, b: number): number => a * b;

/* 可选参数:加 ? */
function greet(name: string, greeting?: string): string {
  return `${greeting ?? "你好"}${name}`;
}

/* 参数默认值:不传就用默认值 */
function createUser(name: string, role: string = "user") {
  return { name, role };
}

接口(Interface)

接口用来定义对象的形状——它有哪些字段、每个字段是什么类型。

TypeScript
/* 定义一个接口,描述"用户"对象的形状 */
interface User {
  id: number;
  name: string;
  email: string;
  avatar?: string;               /* 可选字段(加 ?) */
  readonly createdAt: Date;       /* 只读字段,创建后不能改 */
}

/* 使用接口:必须提供 id/name/email/createdAt */
const user: User = {
  id: 1,
  name: "小明",
  email: "xm@test.com",
  createdAt: new Date()
  /* avatar 不写也行,因为它是可选的 */
};

/* user.createdAt = new Date(); ← ❌ 报错:只读字段不能修改 */
💡 interface vs type

interfacetype 都能定义对象类型。区别:interface 可以被"继承"(extends),初学建议先用 interface

选择题练习 TS-03
可选字段在 interface 中用什么符号标记?
Aavatar??: string
Bavatar?: string
Coptional avatar: string
D[avatar]: string

4. 联合类型与泛型

联合类型(Union Types)

一个变量可以是多种类型之一,用 | 连接。

TypeScript
/* id 可以是数字或字符串 */
let id: number | string;
id = 123;     /* ✅ 数字可以 */
id = "abc";  /* ✅ 字符串也可以 */
/* id = true; ← ❌ 布尔值不行! */

/* 字面量类型:只能是这几个固定值 */
type Status = "pending" | "active" | "deleted";
let userStatus: Status = "active"; /* ✅ */
/* userStatus = "banned"; ← ❌ 不在联合范围内 */

泛型(Generics)

泛型就是"类型版的变量"——普通变量存值,泛型存类型。

TypeScript
/* T 是类型占位符,用的时候才确定具体类型 */
function first<T>(arr: T[]): T {
  return arr[0];
}

const n = first([1, 2, 3]);       /* n 自动推断为 number */
const s = first(["a", "b"]);        /* s 自动推断为 string */

/* 泛型接口:统一的后端响应格式 */
interface ApiResponse<T> {
  code: number;
  data: T;
  message: string;
}
💡 不用怕泛型

泛型看起来吓人,其实就是"类型版的变量"。先读一遍代码,看多了自然就懂了。

预测输出练习 TS-04
const result = wrap(42);中,result 的类型?
function wrap<T>(val: T): T[] { return [val]; } const result = wrap(42);
Anumber
Bnumber[]
Cany[]
DT[]

5. JavaScript 核心语法

TypeScript 最终编译成 JavaScript 运行。下面是 JS 核心语法,你可以在浏览器里直接运行

JavaScript
/* const: 不可重新赋值(推荐默认用 const) */
const name = "小明";

/* let: 可重新赋值 */
let age = 25;
age = 26; /* ✅ 可以改 */

/* var: 老写法,有作用域问题,不要用了 */

/* 模板字符串:用反引号 + ${} 嵌入变量 */
console.log(`${name} 今年 ${age} 岁`);
🟨 JS 编辑器 — 改代码看效果
🗣️ 大白话翻译

下面代码在干啥:把"小明"装进叫 name 的盒子,25 装进 age,然后用 console.log 把"你好 小明,你今年 25 岁"打印到下方。

怎么改:把引号里的"小明"改成你的名字,把 25 改成你的年龄,点 ▶运行 看变化。

点 ▶运行 看输出

6. 数组与对象

数组方法

JavaScript
const nums = [1, 2, 3, 4, 5];

/* map: 对每个元素做变换,返回新数组 */
const doubled = nums.map(n => n * 2);  /* [2, 4, 6, 8, 10] */

/* filter: 过滤符合条件的元素 */
const evens = nums.filter(n => n % 2 === 0); /* [2, 4] */

/* reduce: 累加计算 */
const sum = nums.reduce((acc, n) => acc + n, 0); /* 15 */

/* find: 找第一个满足条件的元素 */
const found = nums.find(n => n > 3); /* 4 */

/* forEach: 遍历每个元素(不返回新数组) */
nums.forEach(n => console.log(n));

对象与解构

JavaScript
const user = {
  name: "小明",
  age: 25,
  city: "广元市旺苍县"
};

/* 解构赋值:一次性取出多个字段 */
const { name, city } = user;
console.log(name, city); /* 小明 广元市旺苍县 */

/* 展开运算符:复制对象并修改部分字段 */
const updated = { ...user, age: 26 };
console.log(updated); /* { name: "小明", age: 26, city: "广元市旺苍县" } */
预测输出练习 JS-05
以下代码的输出?
const arr = [1, 2, 3, 4]; const result = arr.filter(n => n > 2).map(n => n * 10); console.log(result);
A[10, 20, 30, 40]
B[30, 40]
C[3, 4]
D[1, 2, 3, 4]

7. 异步编程 — Remotion 逐行讲解

JavaScript 是单线程的,但通过异步机制可以处理网络请求、文件读写等耗时操作。

REMOTION STYLE
🎬 逐行讲解 · async/await 异步编程
第 1 步
1/0
💡 Promise 三状态

Promise 有三种状态:pending(等待中)→ fulfilled(成功)/ rejected(失败)。await 只能在 async 函数里用,它会暂停执行直到 Promise 完成。

填空题练习 JS-06
让 fetch 在完成前阻塞:在这条 const 语句中填关键字
async function getData() { const res = fetch(url); return res.json(); }

8. Python 基础

Python 语法接近自然语言,是最适合入门的编程语言

变量与字符串

Python
# 变量不需要声明类型(Python 是动态类型)
name = "小明"
age = 25
height = 1.75
is_student = True  # 布尔值,注意首字母大写

# f-string(类似 JS 模板字符串)
print(f"{name} 今年 {age} 岁,身高 {height} 米")

# 多行字符串:用三个引号
text = """这是
多行
文本"""

# 字符串常用方法
print("hello".upper())       # 转大写:HELLO
print("  hi  ".strip())        # 去空格:hi
print("a,b,c".split(","))      # 分割:['a', 'b', 'c']

控制流

Python — 注意冒号和缩进(4个空格)
score = 85

# if / elif / else — 用冒号开头,缩进表层级
if score >= 90:
    print("优秀")
elif score >= 80:
    print("良好")
elif score >= 60:
    print("及格")
else:
    print("不及格")

# for 循环:range(5) 生成 0~4
for i in range(5):
    print(i)  # 输出 0 1 2 3 4(每行一个)

# while 循环:条件为真就一直跑
count = 0
while count < 3:
    print(f"当前 count = {count}")
    count += 1
💡 Python vs JavaScript 语法对照
概念PythonJavaScript
变量声明x = 1let x = 1
代码块缩进(4 空格){ } 大括号
布尔值True / Falsetrue / false
空值Nonenull / undefined
条件链if / elif / elseif / else if / else
字符串格式化f"{x}"`${x}`
预测输出练习 PY-07
以下 Python 代码输出什么?
for i in range(3): if i == 1: continue # 跳过本次循环 print(i)
A0 1 2
B0 2
C0 1
D1 2

9. Python 数据结构 — 逐行讲解

列表(List)

Python — 列表 = JS 的数组
fruits = ["苹果", "香蕉", "橙子"]
fruits.append("葡萄")     # 末尾添加元素
fruits.insert(0, "西瓜")   # 在指定位置插入
fruits.remove("香蕉")      # 删除指定元素
print(fruits[0])            # 访问第一个
print(fruits[-1])           # 访问最后一个(负数从末尾计)
print(len(fruits))          # 获取长度

字典(Dict)— Python 核心数据结构

REMOTION STYLE
🎬 逐行讲解 · Python 字典操作
第 1 步
1/0
预测输出练习 PY-08
列表推导式的结果?
result = [x * 2 for x in range(4) if x > 0] print(result)
A[0, 2, 4, 6]
B[2, 4, 6]
C[1, 2, 3]
D[2, 4]

10. 函数与文件操作

函数

Python
# 基本函数定义
def add(a, b):
    return a + b

# 默认参数:不传就用默认值
def greet(name, greeting="你好"):
    return f"{greeting}{name}"

print(greet("小明"))        # 输出:你好,小明
print(greet("小明", "哈喽"))  # 输出:哈喽,小明

# 不定长参数:*args 接收任意数量参数
def sum_all(*numbers):
    return sum(numbers)

print(sum_all(1, 2, 3, 4))  # 输出:10

# Lambda 匿名函数(类似 JS 箭头函数)
square = lambda x: x ** 2
print(square(5))  # 输出:25

文件操作

Python — with 语句自动关闭文件
# 写文件("w" 模式:覆盖写入)
with open("data.txt", "w", encoding="utf-8") as f:
    f.write("第一行\n")
    f.write("第二行\n")

# 读文件("r" 模式:只读)
with open("data.txt", "r", encoding="utf-8") as f:
    content = f.read()        # 一次性读取全部
    print(content)

# 逐行读取(适合大文件)
with open("data.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.strip())
💡 with 语句

with 打开文件,Python 会在代码块结束时自动关闭文件,不需要手动 f.close()

填空题练习 PY-09
定义接收不定长参数并求和的函数:
def sum_all(): return sum(numbers)

11. 面向对象编程

Python 的类(class)用来创建自定义数据类型。

Python
class Dog:
    # __init__ 是构造方法,创建实例时自动执行
    def __init__(self, name, breed, age):
        self.name = name       # 实例属性:每个狗名字不同
        self.breed = breed     # 品种
        self.age = age         # 年龄

    # 实例方法:self 指向调用它的那只狗
    def bark(self):
        return f"{self.name} 汪汪叫!"

    def birthday(self):
        self.age += 1
        return f"{self.name} 过完生日,{self.age} 岁了"

# 创建两只狗
dog1 = Dog("旺财", "中华田园犬", 3)
print(dog1.bark())       # 旺财 汪汪叫!
print(dog1.birthday())  # 旺财 过完生日,4 岁了
💡 self 是什么

self 就是 Python 版的 this(JavaScript 里的 this)。它指向当前对象实例,每个实例方法的第一个参数必须是 self。

选择题练习 PY-10
Python 类的初始化方法名是?
Aconstructor()
B__init__()
Cinit()
Dnew()

12. FastAPI 入门

FastAPI 是 Python 最现代的 Web 框架——性能极高、自带 API 文档、类型安全、异步支持。

安装

终端
# 安装 FastAPI + uvicorn 服务器
pip install "fastapi[standard]"

# 或用 uv(更现代的包管理器)
uv add fastapi uvicorn

第一个 API

main.py
from fastapi import FastAPI

app = FastAPI()                      # 创建应用实例

@app.get("/")                         # GET 请求,访问根路径
def home():
    return {"message": "Hello, FastAPI!"}

@app.get("/users/{user_id}")         # 路径参数 {user_id}
def get_user(user_id: int):
    return {"user_id": user_id, "name": "用户" + str(user_id)}
终端
# 启动开发服务器(修改代码自动重载)
fastapi dev main.py

# 自动生成的 API 文档(直接在浏览器测试!)
# http://127.0.0.1:8000/docs  → Swagger UI(交互式文档)
# http://127.0.0.1:8000/redoc → ReDoc(美观文档)
✨ FastAPI 杀手锏

你定义好路由后,访问 /docs 就能在浏览器里直接测试每个接口——不需要 Postman!文档全是自动生成的。

选择题练习 FA-11
FastAPI 的交互式 API 文档默认访问哪个路径?
A/docs
B/api-docs
C/swagger
D/documentation

13. CRUD 与 Pydantic 验证 — 逐行讲解

Pydantic 是 FastAPI 的数据验证库。定义模型 → 自动验证 → 生成文档,一条龙。

REMOTION STYLE
🎬 逐行讲解 · FastAPI CRUD 完整流程
第 1 步
1/0
填空题练习 FA-12
FastAPI 中创建新资源用什么装饰器方法?
@app.("/products") def create_product(product: Product): ...

14. 前后端联调

前端 TypeScript 调后端 Python API——全栈开发的本质循环。

后端(Python FastAPI)

main.py — 后端 API 服务
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel

app = FastAPI()

# 允许前端跨域访问(开发时必须加)
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])

class Todo(BaseModel):
    title: str        # 待办标题
    done: bool = False  # 是否完成,默认未完成

todos = []              # 演示用内存存储

@app.get("/api/todos")                    # 读取:获取所有待办
def get_todos():
    return todos

@app.post("/api/todos")                   # 创建:新增待办
def add_todo(todo: Todo):
    todos.append(todo.model_dump())
    return {"ok": True}

前端(TypeScript)

frontend.ts — 前端发送请求
/* 定义接口类型:和后端 Pydantic 模型保持一致 */
interface Todo { title: string; done: boolean; }

/* 获取所有待办:GET 请求 */
async function fetchTodos(): Promise<Todo[]> {
  const res = await fetch("http://localhost:8000/api/todos");
  return res.json();
}

/* 创建新待办:POST 请求,发送 JSON body */
async function createTodo(title: string): Promise<void> {
  await fetch("http://localhost:8000/api/todos", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ title, done: false })
  });
}

/* 使用示例:创建后获取列表 */
createTodo("学完这个教程").then(() => {
  fetchTodos().then(todos => console.log(todos));
});
🎯 全栈数据流

用户操作 → 前端 TS 发 fetch 请求 → 后端 FastAPI 接收 → 处理后返回 JSON → 前端 TS 拿到数据 → 渲染到页面。

预测输出练习 FS-13
前端 fetch 发 POST 时,body 数据需要怎么处理?
A直接传对象,不用处理
BJSON.stringify() 序列化为字符串
CtoString() 转字符串
DFormData() 包装

免费学习资源

TypeScript / 前端

Python / 后端

练习平台推荐

开源全栈项目模板

💡 怎么用模板

不要从零搭项目。先 clone 一个模板跑起来,然后改成自己的业务。比如用 Full Stack FastAPI Template 做后台、Next.js 做前端。

全栈开发学习教程 · TypeScript + Python · GSAP 动画 + Remotion 风代码播放器
所有内容内嵌于单个 HTML 文件,中文注释,可离线使用