Typescript高级: 深入理解Extract类型

干货|如何在项目中使用TypeScript 我们都知道,JavaScript是一门非常灵活的编程语言,这种灵活性一方面使得它成为最受欢迎的编程语言,另一方面也使得它的代码质量参差不齐,维护成本高,运行时错误多。TypeScript是添加了类型系统的JavaScript适用于任何规模的项目。TypeScript的类型系统在很大程度上弥补了JavaScript的缺点。类型系统按照「类型检查的时机」来分类,可以分为动态类型和静态类型动态类型是指在运行时才会进行类型检查,这种语言的类型错误往往会导致运行时错误,我们熟悉的JavaScript。 阅读详情

Extract 概述

  • 在TypeScript这一逐渐成为前端开发首选的静态类型检查语言中,类型系统提供了丰富的工具来帮助开发者编写更加健壮和可维护的代码。
  • 其中,Extract<T, U>是一个强大的内置实用类型,用于从一个联合类型T中提取出属于另一个类型U的那些类型。
  • 本文将深入探讨Extract类型的工作原理、应用场景以及如何有效利用它来提升代码的类型安全性和表达力。

什么是Extract<T, U>?

  • Extract<T, U>是一个条件类型,其定义为:从类型T中选取那些同时也可以被类型U赋值的类型
  • 简而言之,它像一个过滤器,保留了T中与U兼容的部分
  • 在TypeScript的类型系统中,兼容性意味着一个类型可以被另一个类型所赋值
  • 例如,任何派生自基类的类型都可以赋值给基类类型

基本用法

type A = string | number | boolean;
type B = number | boolean;

type C = Extract<A, B>; // 结果为: number | boolean
  • 在这个例子中,Extract<A, B>的结果是A类型中与B兼容的类型,即number和boolean
  • 但是如果是下面这样,则情况不一样
    type A = string | number;
    type B = boolean;
    
    type C = Extract<A, B>; // 结果为: never
    
    • 这里就是 never

应用场景

  • 类型筛选:在处理复杂的联合类型时,Extract可以帮助我们精炼出特定的类型,特别是在大型项目中处理API响应或状态管理时,能够有效地缩小类型范围,提高代码的可读性和准确性

  • 泛型约束:结合泛型使用,Extract可以创建更加灵活且精确的类型约束。例如,在定义一个函数时,可以约束参数类型必须是某联合类型的一个子集,从而限制函数的适用范围

  • 类型映射:在实现类型映射或类型转换时,Extract可以帮助我们基于类型兼容性进行有选择的映射,特别是在处理多态或复杂类型系统设计时

实战案例


1 )从API响应中提取特定类型

  • 假设你正在处理一个API响应,该响应可能包含多种类型的数据,但你只关心其中的某些类型
    type ApiResponse = { type: 'user'; data: User } | { type: 'post'; data: Post } | { type: 'comment'; data: Comment };
    
    type UserSpecificResponse = Extract<ApiResponse, { type: 'user' }>;
    

2 ) 泛型约束与类型映射

  • 考虑一个函数,它应该只处理某些特定类型的对象集合
    // UserSpecificResponse 现在是 { type: 'user'; data: User }
    type Animal = { kind: 'dog' | 'cat' | 'bird' };
    type Canine = { kind: 'dog' };
    
    function processCaninesOnly<T>(items: Array<Extract<T, Canine>>): void {
      // ...
    }
    
    const dogs: Array<{ kind: 'dog' }> = [{ kind: 'dog' }, { kind: 'dog' }];
    processCaninesOnly(dogs); // 正确,因为dogs数组元素的kind只能是'dog'
    

3 ) 高级应用

3.1 基于 Partial 对两个类型求交集

// 定义两个接口  
interface Button {  
  btntype: string;  
  text: string;  
}  
    
interface Link {  
  href: string;  
  text: string; // 假设 Link 接口也有一个 text 属性,以便演示共有属性的合并  
}

// 定义一个函数,接受两个对象,并返回一个包含两者共有属性的新对象  
function mergeCommonProperties<T extends object, U extends object>(obj1: T, obj2: U): Partial<T> & Partial<U> {  
    const result: Partial<T> & Partial<U> = {};  
    // 使用 for...in 循环遍历 obj1 的所有属性  
    for (const key in obj1) {  
        if (obj1.hasOwnProperty(key) && (key as string) in obj2) {  
            // 如果 key 在 obj2 中也存在,则将其添加到结果对象中  
            // 无需显式类型断言,因为 TypeScript 可以自行推断类型  
            result[key] = obj1[key];  
        }
    }
    return result;  
}

// 创建两个符合接口的对象  
const button: Button = {  
    btntype: 'normal',  
    text: 'Click Me',  
};  

const link: Link = {  
    href: 'http://example.com',  
    text: 'Link Text',  
};  

// 使用函数尝试合并共有属性  
const merged = mergeCommonProperties(button, link);  
console.log(merged); // 输出:{ text: 'Click Me' },因为 text 是 Button 和 Link 的共有属性

3.2 基于 in 和 Extract 优化求类型交集

// 定义两个接口  
interface Button {  
    btntype: string;  
    text: string;  
  }  

interface Link {  
    href: string;  
    text: string; // 假设 Link 接口也有一个 text 属性,以便演示共有属性的合并  
}  

// 使用 Extract 和 keyof 来提取两个类型中共有的属性键  
type CommonProperties<T, U> = {  
    [P in Extract<keyof T, keyof U>]: T[P];  
};  

// 定义一个函数,接受两个对象,并返回一个包含两者共有属性的新对象  
function mergeCommonProperties<T extends object, U extends object>(obj1: T, obj2: U): CommonProperties<T, U> {  
    const result: Partial<CommonProperties<T, U>> = {};  

    // 遍历 obj1 的所有属性键  
    (Object.keys(obj1) as Array<keyof T>).forEach(key => {  
        // 检查该属性是否也存在于 obj2 中  
        if ((key as string) in obj2) {  
        // 断言 key 为 Extract<keyof T, keyof U> 类型,表示它是 T 和 U 的共有属性  
        const commonKey = key as Extract<keyof T, keyof U>;  
        // 将共有的属性添加到结果对象中  
        result[commonKey] = obj1[commonKey]; 
        }  
    });  

    // 返回结果,通过类型断言确保类型匹配  
    return result as CommonProperties<T, U>;  
}  

// 创建两个符合接口的对象  
const button: Button = {  
    btntype: 'normal',  
    text: 'Click Me',  
};  

const link: Link = {  
    href: 'http://example.com',  
    text: 'Link Text',  
};  

// 使用函数尝试合并共有属性  
const merged = mergeCommonProperties(button, link);  
console.log(merged); // 输出:{ text: 'Click Me' },因为 text 是 Button 和 Link 的共有属性
  • Extract<T, U>类型是TypeScript中一个强大的工具,它通过条件类型实现了类型筛选,增强了类型系统的灵活性和表达力
  • 在处理复杂类型逻辑、泛型约束以及类型映射时,Extract能够帮助开发者更精细地控制类型系统,写出更加健壮和易于维护的代码
  • 通过上述介绍和案例,希望你能够掌握并充分利用Extract类型在实际项目中的应用,进一步提升你的TypeScript编码体验
在 Typescript 中使用“提取”实用程序类型的最佳方法 在这种情况下,结果OnlyIdKey类型将是包含or 的union字符串文字中的一个。生成的UserKey类型将是来自以字符串“user”开头的字符串的字符串文字的并集。第一个参数是完整的联合体,第二个参数是我们想要得到的联合体的成员。在上面的示例中,我们从联合中删除了所有与数字类型不匹配的文字allTypes。因此,我们只能得到数字。即使我们将值传递给Extract联合中不存在的值,Typescript 也会返回联合中存在的值。在这种情况下,我们要从具有搜索属性的 Routes 联合类型中提取类型。 阅读详情

相关推荐

探索TypeScript的高级类型技巧

本文深入探讨了TypeScript中高级类型技巧的应用,包括如何使用分布式条件类型提取特定类型、按属性种类分组元素,以及如何根据类型而非属性名称来移除对象中的特定属性。文章通过具体的代码示例和类型定义,展示了如何利用TypeScript的类型系统来提高代码的可读性和健壮性。

weixin_42592399的博客 380

typescript 之 Exclude 和 Extract

typescript 种 Exclude 和 Extract 主要就是对多个联合类型的取交集和差集的高级类型。

weixin_44051815的博客 4287

Neurocomputing 投稿指南

Generation Information:选择论文所属领域。上传附件(利益声明,手稿,摘要)审稿人偏好:可以选择期待的审稿人。

qq_41174671的博客 2万+

TypeScript笔记

/定义setTimeout的类型 timeOut = setTimeout(function() {

Ndbsa的博客 544

若依开源框架(分离版)在人大金仓数据库下使用

对于甲方业务特殊要求,使用国产化数据库人大金仓,作为项目主要存储。这里以若依开源框架整合人大金仓为例,演示如何在真实项目中引入人大金仓。

🐱喵测实验室 5943

【项目立项管理、项目整合管理】30天通过软考高项-第二天

①项目或阶段的概述;②范围目标、范围的评估标准,证明达到完⼯标准的证据;③质量目标、项目和产品质量的评估标准、相关核实信息和实际里程碑交付日期以及偏差原因;④成本目标,包括可接受的成本区间、实际成本,产⽣任何偏差的原因等;⑤最终产品、服务或成果的确认信息的总结;⑥进度计划目标,包括成果是否实现项目预期效益:如果在项目结束时未能实现效益,则指出效益实现程度并预计未来实现情况;

weixin_42520723的博客 1002

typeScript内置工具类型,通俗易懂,例子解释(Record、Readonly、Required、Partial、Extract、Exclude、Pick、Omit、NonNullable..)

TS常用内置的工具类型有,Record、Readonly、Required、Partial、Extract、Exclude、Pick、Omit、NonNullable、Parameters、ReturnType。记住这些,在开发中,将会提高我们的开发效率。

qq_920189602的博客 1943

ACM算法模板 · 一些常用的算法模板-模板合集(打比赛专用)

萌新常用的都在这了,本萌新的模板集。

张天枭の博客 5万+

TypeBox条件类型与映射类型终极指南:掌握TypeScript高级类型系统

TypeBox是一个强大的JSON Schema类型构建器,能够创建在内存中的JSON Schema对象并推断为TypeScript类型。在前100字内,TypeBox的核心关键词包括条件类型、映射类型、TypeScript类型系统。这个开源项目让开发者能够在运行时和编译时都获得完整的类型安全保障。🚀 TypeBox的条件类型和映射类型功能让开发者能够在TypeScript中实现复杂的类型逻辑

gitblog_00304的博客 918

QT项目实战:如何在正点原子Linux开发板上集成CVR-100UC身份证阅读器(附完整代码)

本文详细介绍了在正点原子Linux开发板上集成CVR-100UC身份证阅读器的完整实战流程。内容涵盖驱动适配、库文件部署、QT项目框架搭建、核心功能封装以及界面集成,并提供了完整的代码示例,帮助开发者快速实现嵌入式环境下的身份证信息读取功能。

yyy34的博客 258

Spring WebFlux响应式编程实战(三):优雅处理异常与高效调试技巧

本文深入探讨了Spring WebFlux响应式编程中的异常处理与调试技巧。文章通过电商订单流处理场景,详细解析了Reactor核心操作符onErrorReturn、onErrorResume和onErrorMap的实战应用,并介绍了如何构建@ControllerAdvice和WebExceptionHandler全局异常处理防线。同时,提供了使用.log()操作符、Hooks.onOperatorDebug()及BlockHound进行高效调试的方法,旨在帮助开发者构建健壮、可维护的响应式应用。

weixin_29252171的博客 67

The Concise TypeScript Book 系列:深入理解 never 类型——不可达值的类型学意义与实践

`never` 是 TypeScript 内置类型系统中一个极易被忽略、却在类型安全上至关重要的类型。本文以《The Concise TypeScript Book》巴西葡萄牙语版中的 [O tipo never](https://link.gitcode.com/i/54ebcbbe0535c8ba1fb739c966c89e35) 一章为骨架,结合仓库中 [never-type.md](htt

gitblog_00981的博客 793

WinClaw安全实战 02|五层纵深防护体系全解析:从原理到实操,打造零风险AI智能体

2026年AI智能体爆发式普及,OpenClaw以27.3万GitHub星标成为现象级工具,但恶意Skill投毒、提示词注入、数据外泄等安全事故频发,国家互联网应急中心、工信部等多部门接连发布风险警示。威努特基于国家关键信息基础设施安全防护经验,打造WinClaw安全版AI智能体,其核心竞争力在于**五层纵深防护体系**。本文从安全痛点切入,通过真实事故案例揭示风险本质,全景解构五层防护的架构设计与技术原理,逐层拆解身份认证、安装审查、消息拦截、执行约束、监控审计的实现逻辑,搭配20+实操演示、对比表格

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 498

TypeScript进阶 类型演算与高级内置类型

本文深入探讨了 TypeScript 类型演算的原理和应用。通过使用类型演算,我们可以在编译时对类型进行操作和计算,从而提供更强大的类型系统。通过合理地运用类型推断、条件类型、映射类型等工具,我们可以编写更安全、更健壮的代码,并提高开发效率。希望本文能够帮助读者深入理解 TypeScript 类型演算,并在实际开发中得到应用。

1795

基于FPGA的64点fft变换verilog开发

这精度的损失在10bits看来对最后的误差的影响是存在是不可忽略的。此后,在这思想基础上又开发了高基和分裂基等快速算法,随着数字技术的高速发展,1976年出现建立在数论和多项式理论基础上的维诺格勒傅里叶变换算法(WFTA)和素因子傅里叶变换算法。采用这种算法能使计算机计算离散傅里叶变换所需要的乘法次数大为减少,特别是被变换的抽样点数N越多,FFT算法计算量的节省就越显著。采用这种算法能使计算机计算离散傅里叶变换所需要的乘法次数大为减少,特别是被变换的抽样点数N越多,FFT算法计算量的节省就越显著。

FPGA/MATLAB学习教程/源码/项目合作开发 1977

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

深入理解 TypeScript 的 never 类型:永不返回的函数与穷尽性检查实战

`never` 是 TypeScript 类型系统中一个特殊且容易被低估的类型:它代表"永不产生"的值,常被用作无限循环或抛出异常函数的返回类型,也是实现穷尽性检查(exhaustiveness checking)与类型安全的关键工具。本文以 The Concise TypeScript Book 的 [Tipo never](https://link.gitcode.com/i/0056d04b

gitblog_00244的博客 421

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

The Concise TypeScript Book 实战:深入理解条件类型中的 `infer` 类型推断

`infer` 是 TypeScript 条件类型(Conditional Types)中最具威力的关键字之一:它允许你在类型层面“解构”一个类型,把藏在结构内部的成员类型提取出来复用。本文以 The Concise TypeScript Book 中《infer Type Inference in Conditional Types》一章为骨架,结合仓库中[条件类型](https://link.

gitblog_00718的博客 415

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

TypeScript高级类型实战:联合、交叉与条件类型解析

类型系统是现代编程语言的核心机制,通过静态类型检查提升代码质量与开发效率。TypeScript作为JavaScript的超集,其高级类型系统通过联合类型(Union Type)和交叉类型(Intersection Type)实现了灵活的类型组合,配合条件类型(Conditional Type)可创建动态类型逻辑。这些特性在工程实践中能有效解决API响应处理、状态管理、表单验证等场景的类型安全问题,特别适合大型前端项目开发。通过类型守卫和类型推断技术,开发者可以在编译时捕获潜在错误,而映射类型和模板字面量类型

weixin_31315567的博客 231

The Concise TypeScript Book 精讲:分布条件类型(Distributive Conditional Types)的工作原理与实战

本文围绕《The Concise TypeScript Book》中"分布条件类型"这一章节展开,以 [fr-fr 法语版原文档](https://link.gitcode.com/i/7ff4ee59da738c96795fcc8a05847fca) 为核心骨架,并结合仓库内英文原版及相邻章节(条件类型、`infer`、预定义条件类型、映射类型)进行系统化扩展。读者学完后将掌握:分布条件类型为何

gitblog_00042的博客 934

typeScript 基础

基础知识 基础类型: number string boolean array object let a: number = 0 enum: 枚举 常量的集合 // 不赋值 值是从0开始依次往下 enum ActivityStatus { NOT_START, // 0 STARTED // 1 } // 赋值 显示就是对应的值 enum ActivityStatus { NOT_START = 'notStart', STARTED = 'started' } // 使用 const

try it 的博客 194

《The Concise TypeScript Book》:免费开源的 TypeScript 7 系统化学习指南

《The Concise TypeScript Book》是 GitHub 上知名的开源 TypeScript 教程项目(仓库 `gh_mirrors/typ/typescript-book`),它以一本书的完整结构、62 个独立章节的 Markdown 文档,系统覆盖 TypeScript 7 从语言基础、类型系统到高级特性与工具链配置的全部主题。本文以该项目的官方介绍文档([法文版首页](ht

gitblog_00123的博客 243

AccessGuard v0.5:ABAC 属性模型 — TypeScript 联合类型与 Discriminated Union 深度实战

Subject(主体):发起访问请求的实体,通常对应已认证用户。// Subject 属性的抽象基类型// 安全许可级别 1-5Resource(资源):被访问的目标实体。// Resource 属性的抽象基类型Action(操作):对资源执行的具体操作。// Action 操作类型Environment(环境):访问请求发生的上下文。// Environment 属性策略条件(Policy Condition)Policy(策略)

我的博客 451

终极指南:如何用CVA快速解决CSS类管理的混乱局面

你是否曾经为管理UI组件的CSS类名而头疼?🤔 当按钮有不同尺寸、颜色、状态时,你是否发现自己写了无数个重复的CSS类组合?Class Variance Authority(CVA)正是为了解决这个痛点而生的开源工具,它能够让你轻松创建类型安全的UI组件变体,告别繁琐的类名管理。 想象一下,你正在开发一个设计系统,需要为按钮组件定义多种变体:主按钮、次要按钮、小尺寸、中尺寸、禁用状态……传统方

gitblog_00210的博客 985

自然语言驱动的浏览器自动化革命:Stagehand如何重塑Web交互范式

在当今Web应用日益复杂的背景下,开发者面临着一个核心挑战:如何在保持代码简洁的同时,实现复杂的浏览器自动化任务?传统的解决方案如Playwright和Puppeteer虽然强大,但需要开发者编写大量繁琐的DOM操作代码,这不仅增加了开发成本,也限制了非技术人员的参与。Stagehand的出现,正是为了解决这一痛点——通过自然语言和AI驱动的方式,将浏览器自动化从技术专家的专属领域转变为每个开发者

gitblog_00122的博客 894

数据血缘追踪实战:从零开始掌握Marquez项目开发

你是否曾面对数据流向不清、数据来源不明的困扰?在复杂的数据生态系统中,追踪数据的血缘关系就像在大海中寻找特定水滴的源头。Marquez作为开源的数据血缘追踪系统,正是为解决这一痛点而生。本文将带你从实践角度出发,深入探索如何为这个项目贡献代码,成为一名真正的数据血缘追踪专家。 ## 为什么你需要关注数据血缘追踪? 在数据驱动的时代,企业每天处理海量数据转换任务。想象这样一个场景:某个关键业务报

gitblog_00906的博客 962

Copy as Markdown:浏览器内容到Markdown格式的无缝转换解决方案

在日常的技术文档编写、研究资料整理或博客创作过程中,你是否曾为手动将网页内容转换为Markdown格式而烦恼?无论是复制链接时需要手动添加方括号和圆括号,还是整理多个标签页时需要逐个复制粘贴,这些繁琐的操作不仅耗时耗力,还容易出错。Copy as Markdown正是为解决这一痛点而生的浏览器扩展工具,它能够将网页中的链接、图片、选中文本乃至整个窗口的标签页瞬间转换为标准的Markdown格式,让

gitblog_00491的博客 911
上一篇: Typescript高级: 泛型 vs 装饰器
下一篇: Typescript高级: 深入理解交叉类型与联合类型
Wang's Blog
博客等级 码龄12年 7433粉丝 2420原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值