Skip to content

前端核心知识点 02

静态类型检查机制

  • 静态类型:类型在编译时确定,而非运行时。
  • 检查时机:你在 VSCode 里看到的红色波浪线,就是 TSC(TypeScript Compiler)在实时检查。
  • 不改变运行逻辑:TS 编译后会擦除类型,生成纯 JS,所以最终运行的还是 JS 引擎。

类型注解与类型推导

  • 类型注解 显式声明 参数、返回值、未初始化变量
  • 类型推导 自动判断 有初始值的变量、常量

规则:一旦推导完成,就不能违背。 解决:使用接口或类型扩展。

掌握赋值兼容性规则(协变、逆变)

  1. 协变(Covariance)——属性类型协变 属性类型必须是目标类型的超集才能赋值。
  2. 逆变(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 定义了验证器的契约。