困惑

初学 ts 时,extends 让我很困惑:有时它代表 扩大 ,有时代表 缩小 。举几个例子说明:

例1:
class Animal {}
class Dog extends Animal {}

这是 js 本身就有的 class 继承语法,很熟悉了。
Dog 是 Animal 的子类,是对 Animal 的扩展,可以比 Animal 有更多的属性和方法。
extends 似乎代表 扩大

例2:
type MyPick<T, K extends keyof T> = {[P in K]: T[P];
};

K extends keyof T 的含义是“K 是 keyof T 的子集”。K 的取值被限制在 keyof T 内,可以少,不能多。
extends 似乎代表 缩小

例3:
function longest<T extends { length: number }>(a: T, b: T) {return a.length >= b.length ? a : b;
}

T extends { length: number } 要求 T 必须有 length 属性,这样在函数体中才可以直接使用 a.length 和 b.length。
T 除了 length,还可以有其他属性和方法。
extends 似乎代表 扩大


解释

说扩大或者缩小其实含义很模糊,没有实际意义。因为没有明确主语:具体是什么扩大/缩小了。

ts 中的 extends 应该用 子类型(assignable) 去理解。

子类型:如果在期望类型 T 的实例的任何地方,都可以安全地使用类型 S 的实例,那么称类型 S 是类型 T 的子类型。

如果我们能够把任何值赋给类型 T,那么称 T 为顶层类型。其他任何类型都是 T 的子类型。ts 中的顶层类型是 unknown,java 中的顶层类型是 Object

如果类型 T 是其他任何类型的子类型,那么称 T 为底层类型。ts 中的底层类型是 never,是不能被赋值的空类型。可以类比集论中的概念:空集是任何集合的子集。

大白话总结:unknown 是终极父类,never 是终极子类。

所以,子类型 extends 父类型,至于是扩大还是缩小要看考虑问题的角度。用上面的例1说明:

class Animal {}
class Dog extends Animal {}
  • Dog 比 Animal 有更多的属性和方法。这个角度看,Dog 是对 Animal 的扩展。
  • Dog 对 Animal 加了限制,所以 Dog 能取的值比 Animal 要少:Dog 一定是 Animal,但 Animal 不一定是 Dog。这个角度看,Dog 是对 Animal 的缩小

大白话总结:子类特性多了,可取值少了。


引申

前提 Dog extends Animal,考虑下面几种类型的关系:

  • Dog[]Animal[] 的关系
  • () => Dog() => Animal 的关系
  • (arg:Dog) => void(arg:Animal) => void 关系

答案:

  • Dog[]Animal[] 的子类型
  • () => Dog() => Animal 的子类型
  • (arg:Animal) => void(arg:Dog) => void 的子类型。注意这里反过来了。稍微有点绕,用 assignable 的思路去考虑

另外,ts 中强行规定了 (arg:Dog) => void 也是 (arg:Animal) => void 的子类型。这样是不安全的,运行时可能出错。但是 ts “为了方便实现常见的js编程模式“,就是这样设计了。


最后说一说 ts 中的 any。虽然 any 和 unknown 常被放在一起讨论,但其实性质完全不同。在 ts 中,unknownnever 都是正规的类型体系的一部分。但 any 完全在这个体系之外:

ts 中,所有值都可以赋给 any 类型,any 类型的值也可以赋值给其他任何类型,从而绕过类型检查。

写代码时如果用了 any 类型,就代表着:我完全知道我在做什么,这一部分代码的安全与正确性我自己负责。ts 请无视这段代码,不要进行任何类型检查。

extends in typescript相关推荐

  1. TypeScript 里 interface 和 type 的区别

    StackOverflow 上的讨论链接 Interface vs Type alias in TypeScript 2.7 Differences Between Type Aliases and ...

  2. TypeScript内置对象

    前言 JavaScript 中有很多内置对象,它们可以直接在 TypeScript 中当做定义好了的类型. 内置对象是指根据标准在全局作用域(Global)上存在的对象.这里的标准是指 ECMAScr ...

  3. 从0到1落地前端代码检测工具

    点击上方 前端Q,关注公众号 回复加群,加入前端Q技术交流群 中大型公司中前端项目往往不止一个,前端开发人员多加上前端项目众多,为了维持一定的项目团队风格往往十分艰难.这篇文章主要是在公司中针对组内现 ...

  4. 【工程化】1202- 从0到1落地前端代码检测工具

    相关背景: 中大型公司中前端项目往往不止一个,前端开发人员多加上前端项目众多,为了维持一定的项目团队风格往往十分艰难.这篇文章主要是在公司中针对组内现状问题进行问题收集.调研.开发.落地的总结. 1. ...

  5. 【Web技术】1179- 从0到1落地前端代码检测工具

    相关背景: 中大型公司中前端项目往往不止一个,前端开发人员多加上前端项目众多,为了维持一定的项目团队风格往往十分艰难.这篇文章主要是在公司中针对组内现状问题进行问题收集.调研.开发.落地的总结. 1. ...

  6. 手摸手带学妹从0到1落地前端代码检测工具

    点击上方"蓝色字体",选择"设为星标" 做积极向上的前端人! 相关背景: 中大型公司中前端项目往往不止一个,前端开发人员多加上前端项目众多,为了维持一定的项目团 ...

  7. TypeScript 基础学习之泛型和 extends 关键字

    越来越多的团队开始使用 TS 写工程项目, TS 的优缺点也不在此赘述,相信大家都听的很多了.平时对 TS 说了解,仔细思考了解的也不深,借机重新看了 TS 文档,边学习边分享,提升对 TS 的认知的 ...

  8. Typescript中class的extends码源分析

    学习typescript的乐趣在于看它的码源是如何要js实现的. 今天要分析的是类继承的码源.我们先来看一下使用ES5的组合继承是如何做到的: 1 function Person(name) { 2 ...

  9. Typescript中的extends关键字

    前言 extends关键字在TS编程中出现的频率挺高的,而且不同场景下代表的含义不一样,特此总结一下: 表示继承/拓展的含义 表示约束的含义 表示分配的含义 基本使用 extends是 ts 里一个很 ...

最新文章

  1. mysql 西安_MySQL分区维护
  2. 怎样能用计算机打出表白数字,怎么用数字表白?盘点数字表白暗语
  3. css图片的全屏显示代码-css3
  4. 使用 simiki 搭建个人 wiki(简易的博客)
  5. Netty架构与原理详解
  6. matlab神经网络 误差曲线,神经网络如何输出各层训练误差曲线?
  7. 大数据需留意的六个安全问题
  8. 《无线通信与网络》第二章 信号传输基础
  9. mysql 1698 错误
  10. Riverbed连续第四年成为Gartner魔力象限领导者
  11. 京东产品上架如何批量上传商品素材?
  12. nginx部署访问phpadmin
  13. Spring+SpringMVC+MyBatis明日方舟版人员信息管理系统前端页面代码前后端交互+SSM框架 管理员登录 游客登录 普通用户登录 人员的增删改查 信息更新 图片上传 分页查询)
  14. 通信协议-CAN总线
  15. SPSS 调节和中介
  16. MCAL知识点(十九):SENT驱动详细配置
  17. python sys.getsizeof 变量的大小
  18. Javascript夯实基础01
  19. 十二、51单片机之DS1302(SPI)
  20. 传统CD车机面板操作说明

热门文章

  1. Docker(三):部署软件
  2. [软件下载]Skype for Windows 1.1.0.81 Beta
  3. oracle 如何创建、删除用户并授予权限
  4. DAYU200 | 分布式遥控器
  5. MVision Machine Vision 机器视觉
  6. 蒸妙熏蒸,让疾病早缓解,幸福生活更容易
  7. 计算机控制器说法错误的是,江苏专转本计算机每届易出易错题目
  8. 2022北京眼睛健康展,北京眼镜展,北京近视矫正展,眼视光展
  9. 【AD笔记】--原理图原理图库原理图
  10. 【设计模式与Android】备忘录模式——在齐太史简