当前位置: 首页 > news >正文

TypeScript类型兼容性

核心理念

TypeScript的核心特性之一:基于结构(形状)的类型系统
TypeScript关心的不是类型的名称,而是类型的形状。

class Point1 { name: string; age: number; }
class Point2 { name: string; age: number; }const p: Point1 = new Point2(); // 编译通过

尽管 Point1Point2 是两个不同的类,但因为它们具有相同的形状,所以TypeScript认为它们是兼容的。

对象类型的兼容性:成员少的兼容成员多的

对于对象类型(包括类、接口),当赋值给一个要求更“宽泛”的类型时,源类型必须至少包含目标类型的所有必需属性

class Point1 { name: string; age: number; }
class Point2 { name: string; age: number; gender: string; } // 更“具体”的类型const p: Point1 = new Point2(); // 编译通过!

这里,Point2(成员多)可以赋值给 Point1(成员少),因为 Point2 完全覆盖了 Point1 的所有要求。你可以理解为:Point1 的需求只是一个“子集”,而 Point2 提供的“超集”自然能够满足它。接口与类之间也遵循同样的规则。

函数类型的兼容性

函数类型的兼容性更为复杂,需要分别检查参数和返回值。

  1. 参数兼容性:参数多的兼容参数少的(逆变)
    函数参数的类型检查遵循“逆变”原则。简单来说,你可以将一个接受更具体参数的函数(参数少),赋值给一个接受更宽泛参数的函数(参数多)。

    let handler1 = (arg: { name: string; age: number }) => { /* ... */ };
    let handler2 = (arg: { name: string }) => { /* ... */ };handler1 = handler2; // 编译通过
    // handler2 只需要 `name`,而 handler1 提供的参数有 `name` 和 `age`,足够满足 handler2。
    

    从集合论角度看,handler2 的参数类型是 handler1 参数类型的子集。将子集赋值给父集是安全的。原话中“参数多的兼容少的”是一种便于记忆的简化,其本质是逆变。

  2. 返回值兼容性:成员多的兼容成员少的(协变)
    返回值的规则与对象类型类似,遵循“协变”。返回值类型需要更具体,即包含目标类型的所有成员

    interface Animal { name: string; }
    interface Dog extends Animal { breed: string; }let getAnimal = (): Animal => ({ name: 'Generic Animal' });
    let getDog = (): Dog => ({ name: 'Fido', breed: 'Labrador' });getAnimal = getDog; // 编译通过
    // 因为任何需要 Animal 的地方,得到一个拥有更多信息的 Dog 都是安全的。
    
交叉类型:类型的“合并”操作

交叉类型(&)用于将多个类型合并为一个类型,新类型将同时拥有所有类型的成员。它常用于组合对象类型。

interface Person { name: string; }
interface Contact { phone: string; }
type PersonDetail = Person & Contact;let obj: PersonDetail = {name: 'Jack',phone: '133...'
}; // 必须同时拥有 name 和 phone

与接口继承(extends)的关键区别:处理冲突的方式。

  • 接口继承:如果子接口与父接口存在同名但类型不兼容的属性,会直接报错。
    interface A { fn: (value: number) => string; }
    interface B extends A { fn: (value: string) => string; } // 错误
    
  • 交叉类型:会将同名属性进行交叉,通常产生一个重载函数或联合类型。
    interface A { fn: (value: number) => string; }
    interface B { fn: (value: string) => string; }
    type C = A & B;
    // 相当于:fn: ((value: number) => string) & ((value: string) => string);
    // 在实践中,这通常意味着 fn 可以接受 number 或 string 参数。
    
总结

TypeScript的类型兼容性规则围绕着“形状”展开,其核心思想是保证类型安全的前提下提供灵活性。

  • 对象:要满足对方的所有需求(目标类型是源类型的子集)。
  • 函数参数:可以接受更宽泛的输入(逆变)。
  • 函数返回值:需要提供更具体的输出(协变)。
思考题

假设有一个函数类型 type Processor = (data: string | number) => void,以及一个函数 const logger = (data: string) => { console.log(data); }。请问 const p: Processor = logger; 这个赋值是否成立?为什么?这反映了我们上面讨论的哪条规则?

type Processor = (data: string | number) => void
const logger = (data: string) => { console.log(data); }
const p: Processor = logger//赋值是否成立?
http://www.dtcms.com/a/406354.html

相关文章:

  • 软件介绍下载网站建设广安门外网站建设
  • SpringBoot 统一功能处理:拦截器、统一返回与异常处理
  • MySQL 8.0 核心转储优化指南
  • MySQL 学习笔记 (Part.2)
  • 什么是数据治理?有哪些好用的数据治理平台?
  • 【Dubbo】Rpc与HTTP的区别、Dubbo调用过程
  • 网站需要怎么做的吗wordpress nova
  • php 做的应用网站wordpress 模板之家
  • PDFParser 的pickle.loads 寻找链(源码)wmctf2025-pdf2text
  • 如何在业务端进行正确的 reCAPTCHA 验证时序设计
  • 小九源码-springboot048-基于spring boot心理健康服务系统
  • 网站建设收费标准网络营销技术
  • 信息安全基础知识:04网络安全体系
  • 高古楼网站 做窗子pc 手机站网站制作
  • 郑州企业网站快速优化多少钱搜索词和关键词
  • 视频内容审核API选型指南:10大主流接口功能对比
  • shell 编程(1)——vim安装与使用
  • 【后端】.NET Core API框架搭建(11) --对象映射
  • Django+FastAPI+Vue微服务架构指南
  • 今日策略:年化436%,回撤7%,夏普比5.28, deap因子挖掘重构,附python代码
  • 【openrouter.ai】截止2025年9月底 openrouter可用模型清单列表(包含free免费的模型)
  • (13)ASP.NET Core2.2 中的选项模式(Options)
  • 做公司网站需要准备什么苏州网站建设企业
  • giflib5.2.2 在Qt与VS C++中实现Gif缩放示例
  • 题解:AT_abc401_c [ABC401C] K-bonacci
  • 【OpenFeign】在 RuoYi 框架中优雅使用 OpenFeign:从原理到实践与踩坑总结
  • VMware虚拟机安装ubuntu
  • 因果推断落地:从CausalML到EconML,详解Uplift建模核心库
  • 备案个人网站做淘宝客wordpress能做企业站吗
  • 天玑与骁龙芯片:性能对决与选择指南