extends in typescript
困惑
初学 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 中,unknown
和 never
都是正规的类型体系的一部分。但 any 完全在这个体系之外:
ts 中,所有值都可以赋给 any 类型,any 类型的值也可以赋值给其他任何类型,从而绕过类型检查。
写代码时如果用了 any 类型,就代表着:我完全知道我在做什么,这一部分代码的安全与正确性我自己负责。ts 请无视这段代码,不要进行任何类型检查。
extends in typescript相关推荐
- TypeScript 里 interface 和 type 的区别
StackOverflow 上的讨论链接 Interface vs Type alias in TypeScript 2.7 Differences Between Type Aliases and ...
- TypeScript内置对象
前言 JavaScript 中有很多内置对象,它们可以直接在 TypeScript 中当做定义好了的类型. 内置对象是指根据标准在全局作用域(Global)上存在的对象.这里的标准是指 ECMAScr ...
- 从0到1落地前端代码检测工具
点击上方 前端Q,关注公众号 回复加群,加入前端Q技术交流群 中大型公司中前端项目往往不止一个,前端开发人员多加上前端项目众多,为了维持一定的项目团队风格往往十分艰难.这篇文章主要是在公司中针对组内现 ...
- 【工程化】1202- 从0到1落地前端代码检测工具
相关背景: 中大型公司中前端项目往往不止一个,前端开发人员多加上前端项目众多,为了维持一定的项目团队风格往往十分艰难.这篇文章主要是在公司中针对组内现状问题进行问题收集.调研.开发.落地的总结. 1. ...
- 【Web技术】1179- 从0到1落地前端代码检测工具
相关背景: 中大型公司中前端项目往往不止一个,前端开发人员多加上前端项目众多,为了维持一定的项目团队风格往往十分艰难.这篇文章主要是在公司中针对组内现状问题进行问题收集.调研.开发.落地的总结. 1. ...
- 手摸手带学妹从0到1落地前端代码检测工具
点击上方"蓝色字体",选择"设为星标" 做积极向上的前端人! 相关背景: 中大型公司中前端项目往往不止一个,前端开发人员多加上前端项目众多,为了维持一定的项目团 ...
- TypeScript 基础学习之泛型和 extends 关键字
越来越多的团队开始使用 TS 写工程项目, TS 的优缺点也不在此赘述,相信大家都听的很多了.平时对 TS 说了解,仔细思考了解的也不深,借机重新看了 TS 文档,边学习边分享,提升对 TS 的认知的 ...
- Typescript中class的extends码源分析
学习typescript的乐趣在于看它的码源是如何要js实现的. 今天要分析的是类继承的码源.我们先来看一下使用ES5的组合继承是如何做到的: 1 function Person(name) { 2 ...
- Typescript中的extends关键字
前言 extends关键字在TS编程中出现的频率挺高的,而且不同场景下代表的含义不一样,特此总结一下: 表示继承/拓展的含义 表示约束的含义 表示分配的含义 基本使用 extends是 ts 里一个很 ...
最新文章
- R语言ggplot2可视化抑制(部分)图例(legend)输出实战:抑制颜色图例输出、保留数据点形状图例输出
- html多列显示,html – CSS3多列列表
- socket 获取回传信息_基于netty框架的socket长连接负载均衡解决方案 oswl
- BZOJ2525 [Poi2011]Dynamite 【二分 + 贪心】
- Shell 编程快速入门
- VMware View 4.0 测试-7
- 算法——动态规划算法求解字符串的编辑距离
- 终端服务器超出最大允许连接数
- xp系统下如何安装windows phone 7的软件xap文件
- 智慧树工业机器人测试答案_智慧树_工业机器人技术基础_答案章节单元测试答案...
- php 生成导出excel,PHP导出生成EXCEL文件
- failed to create the npcap service 0x8007007e
- Python——click模块
- 利用Java实现将华氏温度转换为摄氏温度
- 13. nginx四层 https代理https 前后端证书配置
- C语言 | C语言深度解剖 ——章节2 符号
- 【产品人生】<基础认知>产品分析方法产品体验分析报告撰写
- 网易杭研易盾实习心得
- android 在线预览pdf文件
- git pull 报错 Your local changes would be overwritten by merge. Commit, stash or revert them to procee