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. IDEA修改数据库信息,结果修改信息中文成 ?

    今天在用IDEA进行插入数据库信息时,发生了一件意想不到的事情,特意记录一下,方便后续查看: 就是我在IDEA的驱动文件中配置了useUnicode = true & characterEnc ...

  2. 学习java的第十六天

    一.今日收获 1.完成了手册第二章没有验证完成的例题 2.预习了第三章的算法以及for语句与if语句的用法 二.今日难题 1.验证上出现问题,没有那么仔细. 2.第二章还有没有完全理解的问题 三.明日 ...

  3. LeetCode两数之和

    LeetCode 两数之和 题目描述 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是 ...

  4. BIO/NIO/AIO对比

    IO 模型 就是使用什么样的通道进行数据的发送和接收,很大程度上决定了程序通信的性能. Java 支持三种网络编程模型:BIO.NIO.AIO. Java BIO,同步并阻塞(传统阻塞型),服务器实现 ...

  5. python web工程师跳巢攻略

    python web工程师跳巢攻略 流程 一面问基础 二面问项目 三面问设计(经验) web请求的流程 浏览器 负载均衡 web框架 业务逻辑 数据库缓存 后端技术栈 python语言基础 语言特点 ...

  6. Vue 之keep-alive的使用,实现页面缓存

    什么是keep-alive 有时候我们不希望组件被重新渲染影响使用体验: 或者处于性能考虑,避免多次重复渲染降低性能.而是希望组件可以缓存下来,维持当前的状态.这时候就需要用到keep-alive组件 ...

  7. 求最长子序列(非连续)的STL方法 - 洛谷P1020 [NOIP1999 普及组] 导弹拦截

    先给出例题:P1020 [NOIP1999 普及组] 导弹拦截 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 大佬题解:P1020 [NOIP1999 普及组] 导弹拦截 - 洛谷 ...

  8. Android Menu的基本用法

    使用xml定义Menu 菜单资源文件必须放在res/menu目录中.菜单资源文件必须使用<menu>标签作为根节点.除了<menu>标签外,还有另外两个标签用于设置菜单项和分组 ...

  9. Mybatis-运行原理

    一.mybatis分层图 二.运行流程 根据全局配置文件创建sqlSessionFactory对象 根据全局配置文件的io流来构建SqlSessionFactoryBuilder对象: 解析(XmlC ...

  10. 【编程思想】【设计模式】【其他模式】blackboard

    Python版 https://github.com/faif/python-patterns/blob/master/other/blackboard.py #!/usr/bin/env pytho ...