ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

type-challenges 实战:从零实现 TypeScript 内置类型 Exclude<T, U>

type-challenges 实战:从零实现 TypeScript 内置类型 Exclude<T, U> 示例工程【免费下载链接】type-challengesCollection of TypeScript type challenges with online judge项目地址https://gitcode.com/GitHub_Trending/ty/type-challenges点击查看免费下载导读本文以 type-challenges 题库第 00043 题Exclude的日文/中文/英文题面为骨架讲解如何在不借助内置ExcludeT, U的情况下用条件类型与分布式行为实现从联合类型T中排除可赋值给U的类型。读完本文你将掌握联合类型、条件类型分布式求值的底层原理并能够独立通过仓库中的类型级测试用例为后续处理Omit、Pick等联合类型操作打下基础。题目背景内置类型 Exclude 是什么ExcludeT, U是 TypeScript 标准库中的一个内置类型工具其作用正如仓库中 README.ja.md日文题面与 README.zh-CN.md中文题面所述从联合类型T中排除U中可赋值的类型来构造一个新的类型原文档英文原文Exclude fromTthose types that are assignable toU。题目给出的示例为type Result MyExcludea | b | c, a // b | c也就是说题目要求我们自己实现一个名为MyExclude的类型它的行为必须与内置的ExcludeT, U完全一致但不允许直接使用内置Exclude本身。这是一道标记为easy初級难度、标签为built-in内置类型与union联合类型的基础题其元数据可在 info.yml 中查看。准备工作仓库中的模板与测试在动手实现之前先了解本仓库为该题提供的两个关键文件起点模板template.tstemplates.ts 只给出一个占位定义类型被写死为any等待我们替换为真正的实现type MyExcludeT, U any类型级测试test-cases.tstest-cases.ts 是本题的类型级验证用例通过type-challenges/utils中导出的Equal与Expect工具进行编译期断言import type { Equal, Expect } from type-challenges/utils type cases [ ExpectEqualMyExcludea | b | c, a, b | c, ExpectEqualMyExcludea | b | c, a | b, c, ExpectEqualMyExcludestring | number | (() void), Function, string | number, ]三个用例分别覆盖了三种典型场景单个字面量排除从a | b | c中排除a期望得到b | c联合类型排除从a | b | c中排除a | b期望得到c函数类型排除从string | number | (() void)中排除Function期望得到string | number因为() void可赋值给Function从而被剔除。这三个用例是判断实现是否正确的唯一标准只要MyExclude满足上述三条断言就等价于内置Exclude。测试工具Equal的实现位于 utils/index.d.ts它通过比较两个函数类型在泛型下的返回值是否一致来严格判断X与Y是否完全相同export type EqualX, Y (T() T extends X ? 1 : 2) extends (T() T extends Y ? 1 : 2) ? true : false这意味着我们不能用any、unknown等宽泛类型蒙混过关MyExclude的结果必须与期望类型精确相等。核心解法利用条件类型的分布式求值分布式条件类型Distributive Conditional Types要理解解法首先要理解 TypeScript 条件类型的一个重要特性当T extends U ? X : Y中的T是裸类型参数naked type parameter且被传入一个联合类型时条件类型会被分发distribute到联合类型的每一个成员上。也就是说对于T a | b | c条件类型T extends U ? X : Y会被展开为(a extends U ? X : Y) | (b extends U ? X : Y) | (c extends U ? X : Y)这正是实现Exclude的基石对联合类型的每个成员分别判断再重新组合成新的联合类型。实现 MyExclude利用分布式条件类型只需一行即可完成实现type MyExcludeT, U T extends U ? never : T逐项拆解其执行过程当T a | b | c、U a时条件类型分发为三个独立的判断a extends a ? never : a结果为never、b extends a ? never : b结果为b、c extends a ? never : c结果为c最终合并为b | c与题目示例一致当U a | b时a与b均命中extends U分支返回never只剩c当T string | number | (() void)、U Function时由于() void可赋值给Function该成员被剔除结果为string | number。这里never的选择非常关键在联合类型中never会被自动吸收即a | never等价于a因此被排除的成员不会残留任何痕迹。这也是排除Exclude语义在类型层面的自然映射。为什么不直接写ExcludeT, U题目明确要求不使用内置的ExcludeT, U这是 type-challenges 系列题目的通用规则见本仓库 README.zh-CN.md 中关于题目源自实际遇到的类型问题不得直接使用内置类型本身的说明。该约束的意义在于强迫学习者理解内置类型底层的实现原理而非黑盒调用帮助建立条件类型 分布式求值 never 吸收的类型思维这套组合拳在后续MyOmit、MyPick、Exclude的兄弟题如Omit、RequiredKeys、OptionalKeys中会反复出现。进阶为什么第一个参数必须是裸类型参数分布式求值有一个容易踩坑的前提被分发的类型参数必须是裸类型参数。如果T被包裹在类型运算中例如T[]、ReadonlyT、(T) void条件类型将不再分发而是对整体进行一次性判断。我们可以做一个反例验证。若把实现写成// 错误示范T 不是裸类型参数不会分发 type WrongExcludeT, U T[] extends U[] ? never : T当传入a | b | c时T被整体视为(a | b | c)[]参与判断而不是对每个成员分别判断结果与期望完全不符。这也是为什么MyExclude的实现必须保持T extends U ? never : T这样直接使用T的形态。顺带一提仓库 utils 中的UnionToIntersectionutils/index.d.ts正是反向利用了这个特性——通过U extends any ? (k: U) void : never强制分发后再求交集可见分布式条件类型在高级类型编程中的核心地位。如何在仓库中验证你的解答本仓库采用 pnpm workspace 管理type-challenges/utils作为工作区包被引用见根目录 package.json 与 utils/package.json。验证方式如下本地类型检查修改 template.ts 中的MyExclude实现使 test-cases.ts 中的三个Expect断言全部通过若任一用例不满足Equal断言TypeScript 编译器会直接报错无需运行任何测试框架在线挑战题目入口位于 README.md 中的 Take the Challenge 徽章链接提交后可在线上 Judge 环境获得即时反馈难度递进建议完成本题后可继续尝试同仓库中依赖联合类型与条件类型的进阶题例如Omit00003-medium-omit、ReadonlyKeys等进一步巩固分布式条件类型的应用。小结本文从 type-challenges 第 00043 题出发完成了从题目解读、测试用例分析到源码实现的全过程ExcludeT, U的语义是从T中排除所有可赋值给U的联合成员标准实现type MyExcludeT, U T extends U ? never : T借助分布式条件类型逐个成员判断再用never的联合吸收特性剔除目标成员验证标准是仓库中 test-cases.ts 的三条Equal断言它们覆盖了单字面量排除、联合排除和函数类型排除三种场景。掌握了这一定义你就掌握了 TypeScript 联合类型运算中最基础、最常用的一块拼图。赞分享示例工程【免费下载链接】type-challengesCollection of TypeScript type challenges with online judge项目地址https://gitcode.com/GitHub_Trending/ty/type-challenges点击查看免费下载相关推荐实现内置 ExcludeT, U从联合类型中排除指定成员type-challenges 第 43 题实现内置 ExcludeT, U 从联合类型中排除指定成员type challenges 第 43 题 本指南围绕 type challenges 仓库示例工程SANA 安装指南从零搭建环境到 Diffusers 快速推理实战SANA 安装指南从零搭建环境到 Diffusers 快速推理实战 本指南是 SANAEfficient High Resolution Image Syn示例工程从零实现 TypeScript 内置 Pick 工具类型type-challenges 第 4 题完整实战解析从零实现 TypeScript 内置 Pick 工具类型type challenges 第 4 题完整实战解析 导读 本文基于 type challenges示例工程上一篇Evolution API缓存策略详解Redis与本地缓存协同下一篇Mac Mouse Fix终极指南让普通鼠标在macOS上媲美苹果触控板的完整教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表