0%

不能承受的生命之轻

从C++入TS

“白海豚”在大地上淫威着,兵荒马乱般的,将狼藉留作了给人们的恶作剧。黑暗的空调房成为我暂时的庇护所。为了理解和学习最入门的ai agent的mcp服务的搭建和微调,在C++数据结构学习之余,我开始着手速通TS。
首先从TS的特性说起,它是一门语言:

1
2
3
4
5
6
7

**1.** javascript的超集,
**2.** 静态类型,在编译期进行类型判断,不用等运行时;
**3.** 类型推断,TS 编译器可以从赋值或返回值推断变量类型,不用手写类型;
**4.** 结构化类型:看”形状”不看名义,只要结构匹配就能够赋值,不需要显式继承;
**5.** 类型仅存在于编译器,编译后即为纯JS,运行时零开销。

也许是因为学习进度的问题,我在TS接触到了C++中没有接触过的内容(我在开始接触数据结构的学习也是速通的C转的cpp,没有系统学过cpp,可能对于类和继承这些并没有涉及,本着用什么就学什么的实用主义,倒也省了许多时间),也可以算是一种新的特性,就是类的封装和接口。这个在平时刷题的时候都被Leetcode巧妙地隐藏了,所以即使是刷算法题,也感知不深。

首先我们看其中TS最标志性的接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

type Gender = 'man'|'woman';

/* const gender: Gender = 'woman'; (本条仅供调试使用) */

interface User{
name: string;
age: number;
id: number | string /*这里还可以填自定义的类型,“|”表示联合类型*/;
gender: Gender;
}
class UserImpl implements User{
constructor(
public name:string,
public age:number,
public id:number | string,
public gender: Gender,
)/*
这一段函数体可以留空,TS会帮你填好
{
this.name = name;
this.age = age;
this.id = id;
this.gender = gender;
}*/
}

首先我们看最表面的一层,就是变量类型声明。与C++不同,TS的类型声明在变量之后,使用 “:” 隔开。常见的变量类型有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

基础类型

  number / string / boolean / null / undefined / symbol / bigint / void

 特殊类型

      1.any       → 放弃检查(应急逃生口,应少用)

      2.unknown   → 安全版 any,使用前必须窄化

      3.never     → 永不返回(抛异常/死代码),也做穷尽性检查

字面量类型

        'man' | 'woman'   → 值只能是列举出的那几样(见"类型组合")

其中字面量类型包括:联合类型和交叉类型,这个可以联想到我们在高中学习过的集合交并运算。联合运算符 “|” 等价于数学上的 “” ,交叉运算符 “&” 等价于数学上的 “” ,通过这个我们完成了对 “Gender” 的定义。

然后我通过 “interface” 将 “User” 的类型抽象为接口,实际上解释规定了一个协议,所有使用该接口的变量都会被其中定义的类型约束,如果在编译期出现任何错误,都能标出,极大地方便了多人协作。如果既需要约束形状又要实现,我们会同时使用 “class implements” 和 “interface”。对于 “class+new” 和 “interface”,“struct” 和 “interface”,我做出如下对比:

维度 C++ struct TS interface TS 对象字面量
值容器 struct User { ... } 描述形状的合同 { name, age } 普通对象
运行时存在 ✅ 真实内存布局 ❌ 编译后消失 ✅ 普通对象
能 new new User() / 甚至栈上 User u; ❌ 不能 不用 new,直接写 {...}
方法/行为 ✅ 可以有 ❌ 只声明签名
私有/封装
什么时候用 C++ 世界的值容器 描述"长什么样" TS 世界的值容器
维度 class interface
本质 具体蓝本,能 new 出对象 抽象约定(形状),只有类型
运行时存在 ✅ 编译后变成 JS class ❌ 完全被擦除
能实例化 new ❌ 永远不能
内容 字段 + 方法实现 + 构造函数 只声明签名
继承 extends 单继承 extends 可多继承
复用什么 实现(方法体 + 状态) 形状/合同(签名)
任意对象自动满足 ❌ 有 private 就锁死 ✅ 结构化,无需改造
复用第三方代码 ❌ 必须继承它 ✅ 不用动它
声明合并
多"能力"组合 ❌ 单继承 ✅ 多继承
独有能力 构造函数、private、static、get/set、instanceof 形状约束、声明合并、函数类型、多继承
这样我们就可以得出 interface 的优点:
收益 说明 示例
🛡️ 编译期拦截 字段拼错、类型不对、漏字段 → 立刻报错 gender: 'boy'
💡 自动补全 编辑器列出有哪些字段 user. + Ctrl+Space
🧱 函数契约 参数形状明确,调用方不猜 function register(u: User)
📡 API 建模 描述后端 JSON 形状 Promise<User>
🔧 重构安全 改形状,所有引用点一起报错 字段改名全项目红色波浪线
🔄 多态替换 同一形状多个实现随意换 Repository 接口

理解了这些,我们就可以进入mcp服务搭建的学习了。

云卷云舒

“卧看满天云不动,不知云与我俱东。”悠然恣意,像是卧在船上,任凭扁舟弄发,鸟雀呼晴。恰日落橘黄,草木弄晴,风儿潜入夜,阑阑珊珊,卷走了湿气。没有桨叶的小舟骀荡着,漫无目的,仿佛寄蜉蝣于天地,渺沧海之一粟,仅仅是予此一念,便已是沁出一层冷汗——思考杀死了意义,存在背叛了永恒————我于此间徜徉。