🎖️typeScrpt中如何使用条件类型和泛型?

简介: 我将通过一个可能对日常使用非常有帮助的代码示例更深入地介绍泛型。

嗨,大家好!这里是道长王jj~ 🎩🧙‍♂️

我将通过一个可能对日常使用非常有帮助的代码示例更深入地介绍泛型。

我们有一个函数,根据作为参数传递的格式,可以将对象序列化为不同的格式:

type JsonFormat = {
    type: "json" };
type BinaryFormat = {
    type: "binary" };
type StreamFormat = {
    type: "stream" };
type Format = JsonFormat | BinaryFormat | StreamFormat;

function serialize(
  obj: Record<string, unknown>,
  format: Format,
): any {
   
  // ...
}

我们期望每个函数调用的返回类型根据格式而异:

const data = {
    a: 1, b: 2 };
// 格式为 json,返回类型应为字符串
const s1 = serialize(data, {
    type: "json" });  
// 格式为 binary,返回类型应为 Uint8Array  
const s2 = serialize(data, {
    type: "binary" });  
// 格式为 stream,返回类型应为 ReadableStream<Uint8Array>
const s3 = serialize(data, {
    type: "stream" });

为了实现这一点,我们需要将 format 参数的类型连接到函数的实际返回类型。首先,在函数签名中添加一个泛型类型参数 TFormat

// ...
type Format = JsonFormat | BinaryFormat | StreamFormat;

function serialize<TFormat extends Format>(
  obj: Record<string, unknown>,
  format: TFormat,
): any {
   
  // ...
}

泛型类型参数 TFormat 使用 extends 关键字将类型限制为特定类型或类型集。在这种情况下,它确保只有 Format 联合类型的子类型可以用作输入参数。

接下来,我们创建泛型类型 SerializeReturnType 来为每种格式选择正确的返回类型:

// ...
type Format = JsonFormat | BinaryFormat | StreamFormat;

type SerializeReturnType<TFormat extends Format> = 
  TFormat extends JsonFormat 
  ? string
  : TFormat extends BinaryFormat
  ? Uint8Array
  : TFormat extends StreamFormat
  ? ReadableStream<Uint8Array>
  : never;

// ...

这个泛型类型根据泛型类型参数 TFormat 返回正确的类型。类型定义使用条件类型将每种可能的格式映射到其相应的返回类型。 ?: 字符序列实际上是嵌套的三元表达式。因此,您可以将此类型定义视为 if-else-if 梯形:

  • 如果 TFormatJsonFormat,则返回类型是 string
  • 否则,如果 TFormatBinaryFormat,则返回类型是 Uint8Array
  • 否则,如果 TFormatStreamFormat,则返回类型是 ReadableStream<Uint8Array>
  • 否则,如果 TFormat 不是这三种类型之一,返回类型是 never,这意味着该函数不能返回任何内容。

最后,我们需要将参数 format 的泛型类型连接到函数的泛型返回类型:

// ...
type Format = JsonFormat | BinaryFormat | StreamFormat;

type SerializeReturnType<TFormat extends Format> = 
  TFormat extends JsonFormat 
  ? string
  : TFormat extends BinaryFormat
  ? Uint8Array
  : TFormat extends StreamFormat
  ? ReadableStream<Uint8Array>
  : never;

function serialize<TFormat extends Format>(
  obj: Record<string, unknown>,
  format: TFormat,
): SerializeReturnType<TFormat> {
   
  // ...
}

这样,函数的返回类型会根据传递的格式而自动确定,并且在类型检查中会得到正确的类型信息。它展示了泛型的强大功能,使我们能够根据参数的类型来推断返回类型。


🎉 你觉得怎么样?这篇文章可以给你带来帮助吗?当你处于这个阶段时,你发现什么对你帮助最大?如果你有任何疑问或者想进一步讨论相关话题,请随时发表评论分享您的想法,让其他人从中受益。🚀✨

目录
相关文章
|
前端开发 C#
C# 基于NPOI+Office COM组件 实现20行代码在线预览文档(word,excel,pdf,txt,png)
C# 基于NPOI+Office COM组件 实现20行代码在线预览文档(word,excel,pdf,txt,png)
载波相移CPS-SPWM调制方法的simulink建模与仿真
本课题研究载波相移CPS-SPWM调制方法的Simulink建模与仿真。CPS-SPWM通过在多个功率单元中引入载波相移,使开关动作错开,输出多电平PWM波形,接近理想正弦波。系统采用单极倍频调制波反相法,生成互补脉冲序列控制开关管通断。双极性CPS-PWM的电压电平数为n+1,基波分量是单个双极性PWM的N倍。仿真结果验证了该方法的有效性,核心程序基于MATLAB2022a实现。
|
10月前
|
Web App开发 搜索推荐 开发者
浏览器插件上架指南:如何把你的产品搬上浏览器插件市场
在实践了 Chrone、Firefox、Edge、Opera 等 几个主要的插件平台的上架发布工作后,我觉得很有必要把这个过程和思考记录下来,分享给大家,希望能提供一些参考和避坑的经验。我想通过这篇文章,和大家聊聊「为什么我要做这件事」,以及「这个系列文章会包含哪些内容」。我想用一个系列的文章,记录我是如何把 EmojiClick 搬到浏览器插件市场的,也给大家提供一些借鉴经验。
271 19
|
前端开发 持续交付 UED
模块联邦的适用场景
【10月更文挑战第25天】模块联邦适用于需要实现模块共享、组合、拆分和重组的场景,可以提高应用的可维护性、扩展性、灵活性和性能。在实际应用中,需要根据具体的需求和项目特点选择合适的模块联邦方案,并结合其他技术和工具进行综合应用。
|
缓存 监控 数据挖掘
C# 一分钟浅谈:性能测试与压力测试
【10月更文挑战第20天】本文介绍了性能测试和压力测试的基础概念、目的、方法及常见问题与解决策略。性能测试关注系统在正常条件下的响应时间和资源利用率,而压力测试则在超出正常条件的情况下测试系统的极限和潜在瓶颈。文章通过具体的C#代码示例,详细探讨了忽视预热阶段、不合理测试数据和缺乏详细监控等常见问题及其解决方案,并提供了如何避免这些问题的建议。
280 7
|
存储 分布式计算 监控
Hadoop在云计算环境下的部署策略
【8月更文第28天】Hadoop是一个开源软件框架,用于分布式存储和处理大规模数据集。随着云计算技术的发展,越来越多的企业开始利用云平台的优势来部署Hadoop集群,以实现更高的可扩展性、可用性和成本效益。本文将探讨如何在公有云、私有云及混合云环境下部署和管理Hadoop集群,并提供具体的部署策略和代码示例。
501 0
|
存储 传感器 大数据
大数据定义详解
【4月更文挑战第9天】大数据,超常规工具处理的海量(TB-PB-EB)多样化数据,包含结构化与非结构化信息,生成速度快且真实性高。关键在于专业化处理以实现数据增值,依赖于计算机科学、统计学的理论与云计算的支撑。大数据分析提供决策支持,驱动业务创新和社会治理改善,与云计算紧密关联,共同塑造新兴领域。
784 4
|
JavaScript Java Docker
使用 Dockerfile 构建和定制 Docker 镜像
Dockerfile是构建Docker镜像的文本文件,包含一系列指令,如`FROM`, `WORKDIR`, `COPY`, `RUN`, `EXPOSE`和`CMD`。它用于自动化`docker build`命令来创建Image。使用Dockerfile可以基于官方镜像定制应用镜像,方便应用容器化和扩展。基本流程包括选择基础镜像、设置工作目录、安装依赖、暴露端口和定义启动命令。构建镜像使用`docker build`,运行容器用`docker run`。了解并熟练使用Dockerfile能提升容器化部署效率。
|
存储 JavaScript 前端开发
JavaScript 自定义对象 及 new()原理与实现 如何完整地手写实现new
JavaScript 自定义对象 及 new()原理与实现 如何完整地手写实现new
310 0
|
Linux 网络安全 Apache
安装Apache之后,在浏览器中无法访问问题
安装Apache之后,在浏览器中无法访问问题
385 0