Typescript高级: 深入理解infer关键字

2024-06-02 04:52

本文主要是介绍Typescript高级: 深入理解infer关键字,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

概述

  • 在 TS 中,infer 是一个高级类型操作,特别是条件类型和映射类型中非常有用的关键字
  • 它在泛型中使用也会是一个强大工具,增强了类型推断的能力,让开发者更灵活地处理和操作类型
  • 它允许在泛型类型推导过程中捕获一个具体的类型,这对于编写复杂的类型转换和映射操作特别有用
  • infer 的定义
    • infer 表示在 extends 条件语句中以占位符出现的用来修饰数据类型的关键字
    • 被修饰的数据类型等到使用时才能被推断出来
  • infer 占位符式的关键字出现的位置
    • infer 出现在 extends 条件语句后的函数类型的参数类型位置上
    • infer 出现在 extends 条件语句后的函数类型的返回值类型上
    • infer 出现在类型的泛型具体化类型上

实现

1 )infer 出现在 extends 条件语句后的函数类型的参数类型位置上

// 定义了一个接口Customer,它描述了一个具有name(字符串类型)和moneyPaid(数字类型)属性的对象
interface Customer {name: stringmoneyPaid: number
}// 定义了一个函数类型,接受一个Customer类型的参数并返回一个字符串
type custFuncType = (cust: Customer) => string// 定义了一个泛型类型inferType<T>,这是理解的重点。这是一个条件类型,它使用了infer关键字
type inferType<T> = T extends (params: infer P) => any ? P : T// 定义了inferResultType类型别名,它是通过将前面定义的custFuncType类型作为参数传递给inferType得到的
type inferResultType = inferType<custFuncType>
  • 分析一下这行代码:type inferType<T> = T extends (params: infer P) => any ? P : T
    • T extends (params: infer P) => any
      • 这部分是一个类型测试,检查T是否可以赋值给一个函数类型
      • 该函数接受一个参数(我们称之为params)
      • infer P关键字在这里用于声明一个新的类型变量P,用来捕获T中函数参数的实际类型
    • ? P
      • 如果上面的测试为真(即T确实是一个函数类型)
      • 那么整个条件类型的结果就是捕获的参数类型P
    • : T
      • 如果上面的测试为假(即T不是函数类型或不匹配)
      • 则条件类型的结果就是T本身,不做任何改变
  • 最后一行代码 type inferResultType = inferType<custFuncType>
    • custFuncType是一个接受Customer类型参数的函数,所以infer P会捕获到这个参数类型
    • 因此,inferResultType 实际上就是Customer类型

2 ) infer 出现在 extends 条件语句后的函数类型的返回值类型上

// 定义了一个接口Customer,它描述了一个具有name(字符串类型)和moneyPaid(数字类型)属性的对象
interface Customer {custname: stringmoneyPaid: number
}
// 这个类型定义了一个函数,该函数接受一个Customer类型的参数并返回一个字符串
type custFuncType = (cust: Customer) => string
type inferType<T> = T extends (params: any) => infer P ? P : T
type inferResultType = inferType<custFuncType>
  • 核心在这里, type inferType<T> = T extends (params: any) => infer P ? P : T
    • 上面,inferType 的 infer 在返回值的位置上
    • infer P 表示“推断出一个类型 P”,这个 P 是函数的返回类型
    • 它根据 extends 的检查结果来选择不同的类型
    • 如果 T 是一个符合 (params: any) => … 形式的函数类型
    • 那么表达式的结果是 P(即函数的返回类型)
    • 否则,表达式的结果是 T 本身
  • 最后,type inferResultType = inferType<custFuncType>
    • 由于,custFuncType 是一个返回值为 string 的函数类型
    • 符合,inferType 内部的三元推导的条件,因为 返回值是 P, 而在这里P又是 string 类型
    • 所以,type inferResultType 就是 string 类型

3 ) infer 出现在类型的泛型具体化类型上

class Subject {constructor(public id: number, public name: string) {}
}const chineseSubject = new Subject(100, "语文");
const mathSubject = new Subject(101, "数学");type ElementOfSet<T> = T extends Set<infer E> ? E : never;const subjectsSet = new Set<Subject>([chineseSubject, mathSubject]);type SubjectType = ElementOfSet<typeof subjectsSet>;// 使用推断出的SubjectType类型
function printSubject(subject: SubjectType) {console.log(`学科ID: ${subject.id}, 学科名称: ${subject.name}`);
}printSubject(chineseSubject);
  • 核心代码在这里:type ElementOfSet<T> = T extends Set<infer E> ? E : never;
    • 如果 参数 T 属于 Set 类型,则 ElementOfSet 则是 E 的类型
    • 这里 Set<infer E> 使用 infer E 推导出 E的类型,如果符合 extends 条件,则返回E,否则返回 never
  • const subjectsSet = new Set<Subject>([chineseSubject, mathSubject]);
    • 这里 subjectsSet 是一个 Set 类型,而且单个元素是 Subject 类型
  • type SubjectType = ElementOfSet<typeof subjectsSet>;
    • ElementOfSet<typeof subjectsSet> 这里符合内部条件,所以,它最终是一个 Subject 类型
  • 所以,在最后,printSubject 中完美运行

总结

  • infer关键字在TypeScript中为泛型编程提供了一个强大的工具
  • 它不仅增强了类型系统的表达能力,还使开发者能够编写出更加灵活和精确的类型定义
  • 通过掌握infer的使用,你能够在处理复杂类型逻辑和类型转换时更加游刃有余
  • 提升代码的类型安全性和可维护性

这篇关于Typescript高级: 深入理解infer关键字的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1023071

相关文章

前端高级CSS用法示例详解

《前端高级CSS用法示例详解》在前端开发中,CSS(层叠样式表)不仅是用来控制网页的外观和布局,更是实现复杂交互和动态效果的关键技术之一,随着前端技术的不断发展,CSS的用法也日益丰富和高级,本文将深... 前端高级css用法在前端开发中,CSS(层叠样式表)不仅是用来控制网页的外观和布局,更是实现复杂交

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

一文带你深入了解Python中的GeneratorExit异常处理

《一文带你深入了解Python中的GeneratorExit异常处理》GeneratorExit是Python内置的异常,当生成器或协程被强制关闭时,Python解释器会向其发送这个异常,下面我们来看... 目录GeneratorExit:协程世界的死亡通知书什么是GeneratorExit实际中的问题案例

kotlin中的行为组件及高级用法

《kotlin中的行为组件及高级用法》Jetpack中的四大行为组件:WorkManager、DataBinding、Coroutines和Lifecycle,分别解决了后台任务调度、数据驱动UI、异... 目录WorkManager工作原理最佳实践Data Binding工作原理进阶技巧Coroutine

深入解析Spring TransactionTemplate 高级用法(示例代码)

《深入解析SpringTransactionTemplate高级用法(示例代码)》TransactionTemplate是Spring框架中一个强大的工具,它允许开发者以编程方式控制事务,通过... 目录1. TransactionTemplate 的核心概念2. 核心接口和类3. TransactionT

深入理解Apache Airflow 调度器(最新推荐)

《深入理解ApacheAirflow调度器(最新推荐)》ApacheAirflow调度器是数据管道管理系统的关键组件,负责编排dag中任务的执行,通过理解调度器的角色和工作方式,正确配置调度器,并... 目录什么是Airflow 调度器?Airflow 调度器工作机制配置Airflow调度器调优及优化建议最

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

c# checked和unchecked关键字的使用

《c#checked和unchecked关键字的使用》C#中的checked关键字用于启用整数运算的溢出检查,可以捕获并抛出System.OverflowException异常,而unchecked... 目录在 C# 中,checked 关键字用于启用整数运算的溢出检查。默认情况下,C# 的整数运算不会自

一文带你理解Python中import机制与importlib的妙用

《一文带你理解Python中import机制与importlib的妙用》在Python编程的世界里,import语句是开发者最常用的工具之一,它就像一把钥匙,打开了通往各种功能和库的大门,下面就跟随小... 目录一、python import机制概述1.1 import语句的基本用法1.2 模块缓存机制1.

深入理解C语言的void*

《深入理解C语言的void*》本文主要介绍了C语言的void*,包括它的任意性、编译器对void*的类型检查以及需要显式类型转换的规则,具有一定的参考价值,感兴趣的可以了解一下... 目录一、void* 的类型任意性二、编译器对 void* 的类型检查三、需要显式类型转换占用的字节四、总结一、void* 的