前端核心知识点 02
静态类型检查机制
- 静态类型:类型在编译时确定,而非运行时。
- 检查时机:你在 VSCode 里看到的红色波浪线,就是 TSC(TypeScript Compiler)在实时检查。
- 不改变运行逻辑:TS 编译后会擦除类型,生成纯 JS,所以最终运行的还是 JS 引擎。
类型注解与类型推导
- 类型注解 显式声明 参数、返回值、未初始化变量
- 类型推导 自动判断 有初始值的变量、常量
规则:一旦推导完成,就不能违背。 解决:使用接口或类型扩展。
掌握赋值兼容性规则(协变、逆变)
- 协变(Covariance)——属性类型协变 属性类型必须是目标类型的超集才能赋值。
- 逆变(Contravariance)——函数参数逆变 函数参数是逆变的:
- 结构化类型 “有这个结构”即可,不看名字
- 超额属性检查 字面量直接赋值时更严格
- 函数参数逆变 参数越“宽”,函数越“通用”
- 上下文类型 根据使用位置自动推导
- 可分配 vs 可扩展 赋值安全 ≠ 对象可变
条件类型与类型守卫
- TypeScript 的类型系统也支持类似的“逻辑判断”——这就是条件类型。
- instanceof 和 in 是 TS 内置的类型守卫(Type Guard),能在运行时检查的基础上,实现类型缩小(Narrowing)
- 使用 is 类型谓词
名义类型 vs 结构类型
- interface 在 TypeScript 中被设计为"开放契约",这意味着它可以被多次声明并且会自动合并
- 与 interface 不同,type 创建的是一个"封闭别名",一旦定义就不能再扩展
interface 和 type 的区别
这个问题看似简单,但实际上涉及 TypeScript 的类型系统设计理念。我认为选择 interface 还是 type 应该基于具体的使用场景和设计意图。
如果我在定义一个类的契约,特别是需要被多个类实现或者支持声明合并的场景,我会选择 interface。比如定义服务接口或者插件系统。
如果我在描述数据结构,特别是函数式编程场景下的数据组合,我会选择 type。比如定义 React 组件的 Props 或者 API 响应结构。
在我最近的项目中,我就遇到了这样的选择。我们在设计一个表单验证库时,使用 type 定义了验证规则的数据结构,同时使用 interface 定义了验证器的契约。