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的更多相关文章

  1. Java EE 编程中路径

    版权声明:未经博主允许,不得转载 首先我们要限定一个范围,是一个项目,或是以个访问地址..就先以一个项目为限定的范围 前述: 学过物理学的都知道相对运动和绝对运动, 虽然是相似的概念,但这里的要简单得 ...

  2. ArcGIS 编程中对接口的理解

    学习AO,最重要的是理解“接口”这个概念.接口是什么?有什么具体作用?在多种计算机高级语言中,都可以看到“接口”这个术语,但基本上每一本书对“为什么使用接口”等重要文都都“语焉不详”,使得初学者往往不 ...

  3. 理解函数式编程中的函数组合--Monoids(二)

    使用函数式语言来建立领域模型--类型组合 理解函数式编程语言中的组合--前言(一) 理解函数式编程中的函数组合--Monoids(二) 继上篇文章引出<范畴论>之后,我准备通过几篇文章,来 ...

  4. 【Java 泛型】之 <? super T> 和<? extends T> 中 super ,extends如何理解?有何异同?

    Java 泛型 <? super T> 和<? extendsT>中 super ,extends怎么 理解?有何不同? 简介 前两篇文章介绍了泛型的基本用法.类型擦除以及泛型 ...

  5. WWDC-UIKit 中协议与值类型编程实战

    本文为 WWDC 2016 Session 419 的部分内容笔记.强烈推荐观看. 设计师来需求了 在我们的 App 中,通常需要自定义一些视图.例如下图: 我们可能会在很多地方用到右边为内容,左边有 ...

  6. Windows 编程中恼人的各种字符以及字符指针类型

    在Windows编程中,很容易见到这些数据类型:LPSTR,LPTSTR,LPCTSTR... 像很多童鞋一样,当初在学Windows编程的时候,对着些数据类型真的是丈二和尚,摸不着头脑,长时间不用就 ...

  7. Java网络编程中异步编程的理解

    目录 前言 一.异步,同步,阻塞和非阻塞的理解 二.异步编程从用户层面和框架层面不同角度的理解 用户角度的理解 框架角度的理解 三.为什么使用异步 四.理解这些能在实际中的应用 六.困惑 参考文章 前 ...

  8. Java基础 -- 深入理解Java类型信息(Class对象)与反射机制

    一 RTTI概念 认识Claa对象之前,先来了解一个概念,RTTI(Run-Time Type Identification)运行时类型识别,对于这个词一直是 C++ 中的概念,至于Java中出现RT ...

  9. Java并发编程中的若干核心技术,向高手进阶!

    来源:http://www.jianshu.com/p/5f499f8212e7 引言 本文试图从一个更高的视角来总结Java语言中的并发编程内容,希望阅读完本文之后,可以收获一些内容,至少应该知道在 ...

随机推荐

  1. 禁止点击、禁止button触发【c#】

    bts.Attributes["onclick"] = "return false; ";

  2. 腾讯云联合中国信通院&作业帮等首发《降本之源-云原生成本管理白皮书》

    在11月4日举办的2021腾讯数字生态大会云原生专场上,腾讯云联合中国信通院.作业帮等率先在国内重磅发布了<降本之源-云原生成本管理白皮书>(简称白皮书),基于腾讯云在业内最大规模的 Ku ...

  3. day02 web主流框架

    day02 web主流框架 今日内容概要 手写简易版本web框架 借助于wsgiref模块 动静态网页 jinja2模板语法 前端.web框架.数据库三种结合 Python主流web框架 django ...

  4. day13 grep命令

    day13 grep命令 linux三剑客之grep命令 介绍 grep(global search regular expression(RE) and print out the line,全面搜 ...

  5. 商业爬虫学习笔记day8-------json的使用

    一. 简介 JSON,全称为JavaScript Object Notation(JavaScript对象标记),它通过对象和数组的组合来表示数据,是一种轻量级的数据交换格式.它基于 ECMAScri ...

  6. 【Linux】【Shell】【Basic】Programming

    shell脚本编程: 编程语言的分类:根据运行方式 编译运行:源代码-->编译器(编译)-->程序文件 解释运行:源代码-->运行时启动解释器,又解释器边解释边运行 根据其编程过程中 ...

  7. 一、手把手教你docker搭建fastDFS文件上传下载服务器

    在搭建fastDFS文件上传下载服务器之前,你需要准备的有一个可连接的linux服务器,并且该linux服务器上已经安装了docker,若还有没安装docker的,先百度自行安装docker. 1.执 ...

  8. Redis,Memcache,MongoDb的特点与区别

    Redis Redis 简介 Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支 ...

  9. 用户信息查询系统_daoImpl

    package com.hopetesting.dao.impl;import com.hopetesting.dao.UserDao;import com.hopetesting.domain.Us ...

  10. 【划重点】Python xlrd简介

    一.用xlrd获取对应数据,并获取所有sheet的名字 import xlrd data=xlrd.open_workbook(r'C:\Users\ASUS\Desktop\重新开始\Python获 ...