如何理解 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语言中的并发编程内容,希望阅读完本文之后,可以收获一些内容,至少应该知道在 ...
随机推荐
- 禁止点击、禁止button触发【c#】
bts.Attributes["onclick"] = "return false; ";
- 腾讯云联合中国信通院&作业帮等首发《降本之源-云原生成本管理白皮书》
在11月4日举办的2021腾讯数字生态大会云原生专场上,腾讯云联合中国信通院.作业帮等率先在国内重磅发布了<降本之源-云原生成本管理白皮书>(简称白皮书),基于腾讯云在业内最大规模的 Ku ...
- day02 web主流框架
day02 web主流框架 今日内容概要 手写简易版本web框架 借助于wsgiref模块 动静态网页 jinja2模板语法 前端.web框架.数据库三种结合 Python主流web框架 django ...
- day13 grep命令
day13 grep命令 linux三剑客之grep命令 介绍 grep(global search regular expression(RE) and print out the line,全面搜 ...
- 商业爬虫学习笔记day8-------json的使用
一. 简介 JSON,全称为JavaScript Object Notation(JavaScript对象标记),它通过对象和数组的组合来表示数据,是一种轻量级的数据交换格式.它基于 ECMAScri ...
- 【Linux】【Shell】【Basic】Programming
shell脚本编程: 编程语言的分类:根据运行方式 编译运行:源代码-->编译器(编译)-->程序文件 解释运行:源代码-->运行时启动解释器,又解释器边解释边运行 根据其编程过程中 ...
- 一、手把手教你docker搭建fastDFS文件上传下载服务器
在搭建fastDFS文件上传下载服务器之前,你需要准备的有一个可连接的linux服务器,并且该linux服务器上已经安装了docker,若还有没安装docker的,先百度自行安装docker. 1.执 ...
- Redis,Memcache,MongoDb的特点与区别
Redis Redis 简介 Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支 ...
- 用户信息查询系统_daoImpl
package com.hopetesting.dao.impl;import com.hopetesting.dao.UserDao;import com.hopetesting.domain.Us ...
- 【划重点】Python xlrd简介
一.用xlrd获取对应数据,并获取所有sheet的名字 import xlrd data=xlrd.open_workbook(r'C:\Users\ASUS\Desktop\重新开始\Python获 ...