如何理解 TS 类型编程中的 extends 和 infer
extends
extends 在TS类型编程中用法(T extends U),表示 T 中的某些在 U 里面,比较难描述,用法如下:
T extends U ? X : Y
分为两种情况理解更直观一些:
1)如果 T 不是一个联合类型,表示如果 T 是 U 的子集,那么返回 X 否则返回 Y。
举个例子,在下面的例子中,如果 T 是 U 的子集,那么返回 number,否则返回 never。
export type TExtends<T, U> = T extends U ? number : never;
// T(number)是 U(number | string)的子集,所以返回number
type TExtendsExample1 = TExtends<number, number | string>; // number
// T(boolean) 不是 U(number | string)的子集,所以返回never
type TExtendsExample2 = TExtends<boolean, number | string>; // never
2)如果 T 是一个联合类型,表示如果 T 中的类型是 U 的子集,那么返回 X 否则返回 Y。这个过程可以理解为对T中的类型进行一次遍历,每个类型都执行一次 extends。
举个例子:
下面的例子中对 T 中的每个类型进行遍历,检测是否是 extends 于 null 或 undefined。如果满足这个条件就返回 never(对于联合类型来说如果返回never那就相当于不存在,因为never是所有类型的子类型),如果不满足就返回原来的类型。
type NonNullable<T> = T extends null | undefined ? never : T;
// T(number | string) 不是 U(null | undefined) 的子集,所以返回 T
type TNonNullableExample1 = NonNullable<number | string>; // number | string
// T(string | null) 中 string 不是 U 的子集返回 string,null 是 U 的子集,返回 never
type TNonNullableExample2 = NonNullable<string | null>; // string
infer
infer 可以推断一个类型变量,常见用法示例:
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
infer R 相当于声明一个类型变量,这个变量的类型取决于传入的泛型 T,在之前的时候 extends 右边的类型是写死的,但是在这里通过 infer R 来代替写死的类型,并且具体的类型取决于传入的泛型。
不过需要注意,R 变量只能在 true 的分支可以使用,也就是只能在 ? 的第一个分支中使用。
下面通过两个例子进行说明:
1)如果 T 是 () => infer R 的子集,那么返回 R,否则返回 number
{
type Func<T> = T extends () => infer R ? R : number;
// T(string) 不是 () => infer R 的子集,因此返回 number
type TFuncExample1 = Func<string>; // number
// T(() => boolean) 是 () => infer R 的子集,并且通过传入的() => boolean可以推断出 R 是 boolean,因此返回 R(boolean)
type TFuncExample2 = Func<() => boolean>; // boolean
}
2)如果 T 是 {a: infer VType, b: infer VType} 的子集,那么返回 UType | VType,否则返回number。
type TObj<T> = T extends { a: infer VType, b: infer UType} ? VType | UType : number;
// T(string)不是 {a: infer VType, b: infer UType} 的子集,因此返回 number
type TObjExample1 = TObj<string>; // number
// T(string)是 {a: infer VType, b: infer UType} 的子集,因此返回 UType | VType
type TObjExample2 = TObj<{ a: number, b: string }>; // => number | string
完。
如何理解 TS 类型编程中的 extends 和 infer的更多相关文章
- Java EE 编程中路径
版权声明:未经博主允许,不得转载 首先我们要限定一个范围,是一个项目,或是以个访问地址..就先以一个项目为限定的范围 前述: 学过物理学的都知道相对运动和绝对运动, 虽然是相似的概念,但这里的要简单得 ...
- ArcGIS 编程中对接口的理解
学习AO,最重要的是理解“接口”这个概念.接口是什么?有什么具体作用?在多种计算机高级语言中,都可以看到“接口”这个术语,但基本上每一本书对“为什么使用接口”等重要文都都“语焉不详”,使得初学者往往不 ...
- 理解函数式编程中的函数组合--Monoids(二)
使用函数式语言来建立领域模型--类型组合 理解函数式编程语言中的组合--前言(一) 理解函数式编程中的函数组合--Monoids(二) 继上篇文章引出<范畴论>之后,我准备通过几篇文章,来 ...
- 【Java 泛型】之 <? super T> 和<? extends T> 中 super ,extends如何理解?有何异同?
Java 泛型 <? super T> 和<? extendsT>中 super ,extends怎么 理解?有何不同? 简介 前两篇文章介绍了泛型的基本用法.类型擦除以及泛型 ...
- WWDC-UIKit 中协议与值类型编程实战
本文为 WWDC 2016 Session 419 的部分内容笔记.强烈推荐观看. 设计师来需求了 在我们的 App 中,通常需要自定义一些视图.例如下图: 我们可能会在很多地方用到右边为内容,左边有 ...
- Windows 编程中恼人的各种字符以及字符指针类型
在Windows编程中,很容易见到这些数据类型:LPSTR,LPTSTR,LPCTSTR... 像很多童鞋一样,当初在学Windows编程的时候,对着些数据类型真的是丈二和尚,摸不着头脑,长时间不用就 ...
- Java网络编程中异步编程的理解
目录 前言 一.异步,同步,阻塞和非阻塞的理解 二.异步编程从用户层面和框架层面不同角度的理解 用户角度的理解 框架角度的理解 三.为什么使用异步 四.理解这些能在实际中的应用 六.困惑 参考文章 前 ...
- Java基础 -- 深入理解Java类型信息(Class对象)与反射机制
一 RTTI概念 认识Claa对象之前,先来了解一个概念,RTTI(Run-Time Type Identification)运行时类型识别,对于这个词一直是 C++ 中的概念,至于Java中出现RT ...
- Java并发编程中的若干核心技术,向高手进阶!
来源:http://www.jianshu.com/p/5f499f8212e7 引言 本文试图从一个更高的视角来总结Java语言中的并发编程内容,希望阅读完本文之后,可以收获一些内容,至少应该知道在 ...
随机推荐
- 一个神奇的JS混淆,JSFuck!
JSFuck,整体由6个字符[, ], (, ), !, +组成,但却是可以正常运行的JS代码,JSFuck程序可以在任何Web浏览器或引擎中运行解释JavaScript! 看一段代码,源代码为:do ...
- celery开启worker报错django.core.exceptions.ImproperlyConfigured: Requested setting INSTALLED_APPS, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE o
其实挺简单的问题,但花了自己一个下午来解决,先是浏览各种博客,无果:没办法,然后去看celery官方文档,无果,近乎绝望,最后仔细看代码,找到问题所在(如下),自学狗这效率...... 下面是自己ta ...
- 【Reverse】每日必逆0x02
BUU SimpleRev 附件 https://files.buuoj.cn/files/7458c5c0ce999ac491df13cf7a7ed9f1/SimpleRev 题解 查壳 拖入iad ...
- Hadoop生态圈学习-1(理论基础)
一.大数据技术产生的背景 1. 计算机和信息技术(尤其是移动互联网)的迅猛发展和普及,行业应用系统的规模迅速扩大(用户数量和应用场景,比如facebook.淘宝.微信.银联.12306等),行业应用所 ...
- window 查看端口占用情况
查看哪个进程在用 netstat -aon|findstr "8080" TCP 0.0.0.0:8080 0.0.0.0:0 ...
- eclips 配置一个tomcat,启动多个不同端口的web项目
前提: 记录这个文章是因为在网上查资料,很多都是,用eclips.配置多个tomcat,就像下面图这样配置两个tomcat 去启动不同的web: 运动多个web 项目,设置不同的端口,需要多个tomc ...
- Selenium和PhantomJS
Selenium Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,类型像我们玩游戏用的按键精灵,可以按指定的命令自动操作,不同是Selenium 可以直接运行在浏览器上, ...
- 商城项目的购物车模块的实现------通过session实现
1.新建购物车的实体类Cart public class Cart implements java.io.Serializable{ private Shangpin shangpin;//存放商品实 ...
- 避免警报疲劳:每个 K8s 工程团队的 8 个技巧
避免警报疲劳:每个 K8s 工程团队的 8 个技巧 监控 Kubernetes 集群并不容易,警报疲劳通常是一个问题.阅读这篇文章,了解减少警报疲劳的有用提示. 如果您是随叫随到团队的一员,您可能知道 ...
- 使用RabbitMQ搭建MQTT服务
由于近期公司需要搭建一套物联网采集环境,底层设备采用MQTT协议传输数据.服务器环境为linux,考虑到现有环境已经有RabbitMQ环境,Rabbit是基于AMQP协议开发的一套高效的消息传输队列. ...