当前位置: 首页 > article >正文

【Typescript】14-高级实战-设计类型安全的-api

高级实战设计类型安全的 API如果学完前面的知识你还只是停留在“我会写几个类型、看得懂一些泛型”那 TypeScript 其实只学了一半。真正拉开差距的地方是你能不能把类型系统转化成设计能力尤其是在 API 设计上。一个成熟的 TypeScript 工程师和一个只是会写注解的开发者最大的区别通常不在语法量而在于前者会主动思考怎样设计一个 API让正确用法自然、错误用法困难、调用成本低、扩展路径清晰。这篇就是收尾篇。它不再单独讲某个语法而是把前面学过的类型映射、联合类型、类型缩小、泛型、索引访问类型、工具类型、运行时校验思路串成一个更接近真实项目的案例。一个现实目标封装类型安全的请求函数假设我们希望封装这样一个函数request(/users);request(/posts);request(/profile);理想效果是不同路径返回不同数据类型编辑器能自动提示合法路径调用方尽量少写额外类型参数错误状态能被明确建模后续增加接口时改动可控这其实就是一个非常典型的 API 设计问题。第一步不要先写函数先写关系表很多人一上来就想写函数签名但更成熟的顺序应该是先写数据关系再写函数。interfaceApiMap{/users:{id:number;name:string;}[];/posts:{id:number;title:string;}[];/profile:{id:number;nickname:string;};}这张映射表非常重要因为它把“路径”和“返回值类型”之间的关系明确了。一旦核心映射关系清楚后面的泛型设计会自然很多。这也是很多类型设计的通用经验不要先想函数长什么样先想系统里有哪些稳定关系。第二步让路径和返回值自动关联asyncfunctionrequestTextendskeyofApiMap(path:T):PromiseApiMap[T]{constresponseawaitfetch(path);returnresponse.json()asPromiseApiMap[T];}这里的关键点有三个T extends keyof ApiMap路径只能来自ApiMap的键path: T调用方传入的路径会绑定到这个类型参数PromiseApiMap[T]返回值会根据路径自动变成对应数据类型于是constusersawaitrequest(/users);constprofileawaitrequest(/profile);此时users会被推断成用户数组profile会被推断成个人信息对象这就是类型安全 API 设计最核心的体验价值调用方几乎不用思考额外类型提示系统已经把正确约束送到了手边。第三步别只建模成功结果失败路径同样是 API 的一部分很多初学者设计 API 时只想着“成功时返回什么”却把失败逻辑推给throw或松散字符串。这样做很常见但类型表达通常不够完整。更好的做法是把成功和失败都纳入模型typeApiSuccessT{success:true;data:T;};typeApiFailure{success:false;error:string;};typeApiResultTApiSuccessT|ApiFailure;这样你的request就可以改造成asyncfunctionrequestTextendskeyofApiMap(path:T):PromiseApiResultApiMap[T]{try{constresponseawaitfetch(path);constdataawaitresponse.json();return{success:true,data};}catch(error){return{success:false,error:errorinstanceofError?error.message:unknown error};}}调用方随之获得的好处很明显constresultawaitrequest(/users);if(result.success){console.log(result.data);}else{console.log(result.error);}这里的success同时承担了业务语义和类型缩小的作用。第四步如果每个接口还有不同参数继续把关系显式写出来真实项目里请求通常不只是一个路径。很多接口还会有不同参数结构。这时你应该继续遵循同一个原则把关系写成映射而不是把复杂度塞进函数实现里。例如interfaceApiParamsMap{/users:{page:number;pageSize:number};/posts:{category?:string};/profile:undefined;}然后可以继续设计asyncfunctionrequestTextendskeyofApiMap(path:T,params:ApiParamsMap[T]):PromiseApiResultApiMap[T]{console.log(path,params);thrownewError(not implemented);}这时request(/users, { page: 1, pageSize: 20 })合法request(/users, { category: ts })报错request(/profile, undefined)合法这种精确约束才是类型系统在 API 设计里的真正价值。第五步如果路径越来越多核心不是写更多泛型而是保证映射结构可维护很多人一学会高级类型就想把所有请求逻辑都压缩成一段复杂的泛型魔法。这样通常走不远。真正成熟的做法是保持系统里有一个清晰、稳定、可维护的“关系源”。也就是说你真正应该投入设计的是路径映射是否清楚参数映射是否清楚成功/失败模型是否统一响应包裹结构是否一致一旦这些关系源稳定泛型函数本身反而会很薄。第六步别被类型安全错觉骗了运行时数据仍然不可信这里必须强调一个现实问题。下面这行代码constdataawaitresponse.json();在运行时拿到的其实只是一个未知值。即使你的函数签名写成了PromiseApiMap[T]也不代表后端真的按照这个结构返回。这就是为什么成熟项目里类型安全 API 设计必须和运行时校验配套。例如constUserSchemaz.object({id:z.number(),name:z.string()});拿到数据后先校验再进入类型系统constparsedUserSchema.parse(data);这一步不是 TypeScript 的补丁而是 TypeScript 真正进入生产环境后的必要搭档。因为 TypeScript 只能保证“你写出来的静态约束”不能替你验证“外部世界真的遵守了这些约束”。第七步API 设计不是类型游戏而是调用体验设计一个好的类型安全 API不是写得越复杂越高级而是调用方会明显感受到自动提示很准错误用法会被及时阻止成功路径和失败路径都清楚不需要频繁手动标类型参数扩展新接口时规律稳定换句话说类型设计的最终价值不在定义文件里而在调用体验里。一个更完整的设计视角如果你把这篇内容和前面的知识串起来会发现一个成熟的 API 类型设计通常包含这些层面用字面量联合或映射表限制合法路径用泛型把路径和返回值关联起来用联合类型表达成功与失败两种结果用判别字段帮助调用方做类型缩小用工具类型和映射类型减少重复用运行时校验处理外部不可信数据这已经不是“我会不会写 TS”层面的问题而是“我会不会设计系统边界”的问题。一个常见误区把复杂度堆进类型而不是整理关系很多人看到优秀库的类型很强就误以为核心在于写出复杂泛型。其实真正的关键往往不是复杂而是关系清晰。如果你的 API 设计本身混乱路径不稳定参数语义模糊返回结构不统一错误处理方式不一致那再多高级类型也救不了这个系统。类型系统最擅长放大清晰关系不擅长拯救混乱设计。最后的判断标准什么叫好的类型安全 API 设计我通常会用这几个问题判断调用方是不是几乎不用额外思考类型正确用法是不是被自然引导错误用法是不是足够难写出来约束是不是和业务真实边界一致后续增加新接口时模式是否仍然统一运行时风险有没有被考虑进来如果这些问题大多数都能回答“是”那你的类型设计通常就是有效的。本文小结TypeScript 的终点不是把所有语法都背熟而是把类型系统转化成工程设计能力。一个好的 API 类型设计会把系统里真实存在的关系显式表达出来再用类型把这些关系自动带到调用方身边让正确用法更自然让错误用法更困难。这就是 TypeScript 最值得投入的地方。它不只是帮你写代码更在帮你设计代码。练习给request增加第二个参数params并让不同路径拥有不同参数类型。尝试为一个前端表单提交函数设计输入类型、成功结果和失败结果并使用判别字段帮助调用方缩小类型。思考哪些地方必须依赖运行时校验而不能只靠 TypeScript请举出你项目里的一个真实例子。后记2026年5月22日于上海。

相关文章:

【Typescript】14-高级实战-设计类型安全的-api

高级实战:设计类型安全的 API 如果学完前面的知识,你还只是停留在“我会写几个类型、看得懂一些泛型”,那 TypeScript 其实只学了一半。真正拉开差距的地方,是你能不能把类型系统转化成设计能力,尤其是在 API 设计上。…...

【Typescript】13-tsconfig与工程化实践

tsconfig 与工程化实践 很多人学 TypeScript 时,会把注意力几乎全部放在语法上:泛型会不会写、infer 看不看得懂、工具类型会不会用。可真正在工程里决定 TypeScript 上限的,往往不是这些,而是 tsconfig.json。因为它决定了编译器…...

【Typescript】12-模块声明文件与第三方库

模块、声明文件与第三方库 当你开始把 TypeScript 真正放进项目里,就会很快遇到一些不再是语法层面的现实问题: 代码和类型应该如何跨文件组织第三方库没有类型时怎么办为什么有些包能直接提示类型,有些却报“找不到声明文件”.d.ts 到底是什…...

【Typescript】11-类抽象类与面向对象建模

类、抽象类与面向对象建模 TypeScript 不是一门纯粹的面向对象语言,但它对类系统的支持足够完整,足以覆盖很多工程场景。问题在于,很多人学到 class 之后,会误以为这就是组织 TypeScript 代码的默认方式。现实恰恰相反&#xff1…...

Perplexity反义词≠低困惑度?——斯坦福NLP实验室内部培训材料首次公开的4层认知陷阱

更多请点击: https://kaifayun.com 第一章:Perplexity反义词≠低困惑度?——认知错位的根源剖析 Perplexity(困惑度)是语言模型评估中被广泛误读的核心指标。许多人直觉认为“低困惑度即好模型”,甚至将“…...

AI生成镜头如何通过DIT审核?——Netflix《The Last Frame》技术白皮书首度公开(附VFX合规性检查清单PDF)

更多请点击: https://kaifayun.com 第一章:AI视频生成在电影制作中的应用 AI视频生成技术正深刻重构电影工业的工作流,从前期预演到后期特效,再到个性化内容分发,其渗透已覆盖创作全生命周期。传统依赖高成本实拍与手…...

Sora 2提示词失效真相大起底(92%用户踩中的3类语义断层陷阱)

更多请点击: https://kaifayun.com 第一章:Sora 2提示词失效的底层归因与认知重构 Sora 2提示词失效并非表层的语法错误或格式偏差,而是源于其多模态对齐机制中语义解码器与时空生成器之间的结构性错配。当用户输入“雨夜东京涩谷十字路口&a…...

【Sora 2批量视频生成黄金工作流】:实测吞吐提升4.8倍的关键配置——NVIDIA A100集群下每小时稳定输出217段1080p视频

更多请点击: https://codechina.net 第一章:Sora 2批量视频生成工作流全景概览 Sora 2作为新一代多模态视频生成模型,其批量处理能力依托于模块化、可编排的端到端工作流设计。该工作流融合提示工程、时空 latent 编码、分块并行解码与后处理…...

从零开发游戏需要学习的c#模块,第二十一章(精灵动画 —— 让角色走起来)

今天我们要学习的内容是 理解精灵图集的原理 加载精灵图集并切帧 实现四方向行走动画 静止时显示待机帧 第一步:准备精灵图集 精灵图集就是一张大图里包含多个小图(帧),播放时依次显示每一帧,形成动画效果。 一…...

黎曼猜想:哲学 × 数学 思维范式全链条

黎曼猜想:哲学 数学 思维范式全链条 华夏之光永存|七大数学猜想思维范式全链条 第二篇开篇 黎曼猜想被公认为数学史上最伟大的未解难题。希尔伯特曾说:“如果我沉睡百年后醒来,第一个问题就是:黎曼猜想证明了吗&…...

P vs NP:西方哲学 × 西方计算理论 —— 人类思维的终极边界

P vs NP:西方哲学 西方计算理论 —— 人类思维的终极边界 华夏之光永存|七大数学猜想思维范式全链条 第一篇开篇 P vs NP 是计算机科学第一难题,克雷数学研究所七大千禧年难题之一。 本文不宣称证明、不跳步、不民科、不超纲。 只用哲学与数…...

暗黑破坏神2存档编辑器完整指南:三步轻松修改D2/D2R角色与装备

暗黑破坏神2存档编辑器完整指南:三步轻松修改D2/D2R角色与装备 【免费下载链接】d2s-editor 项目地址: https://gitcode.com/gh_mirrors/d2/d2s-editor 你是否厌倦了在暗黑破坏神2中反复刷装备却一无所获?是否因为早期加点失误导致角色后期无法应…...

HS2-HF_Patch:Honey Select 2 终极汉化与功能增强完整指南

HS2-HF_Patch:Honey Select 2 终极汉化与功能增强完整指南 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch HS2-HF_Patch 是专为 Honey Select 2 游戏…...

在Nodejs后端服务中集成稳定可靠的大模型能力

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 在Nodejs后端服务中集成稳定可靠的大模型能力 应用场景类,针对需要构建智能对话或内容生成功能的后端工程师&#xff0…...

CANN/pypto copysign函数API文档

# pypto.copysign 【免费下载链接】pypto PyPTO(发音: pai p-t-o):Parallel Tensor/Tile Operation编程范式。 项目地址: https://gitcode.com/cann/pypto 产品支持情况 产品是否支持Ascend 950PR/Ascend 950DT√Atlas A…...

app应用接入广告的完整流程和方法:从零搭建可持续变现体系

随着移动互联网进入存量竞争阶段,用户流量增长趋于饱和,单纯依靠用户新增实现产品增值的模式已然失效。对于绝大多数免费工具、社交、资讯、游戏类 APP 而言,合规、稳定、可持续的广告变现,已经成为补齐产品商业闭环、维持产品长期…...

2026 主流技术栈:hermes agent多环境安装配置:Windows/Mac/Linux

一、Hermes agent 大模型选择 Hermes Agent 通过统一的模型抽象层接入不同厂商的大语言模型服务。实际部署时,建议根据数据合规要求、任务类型和成本预算进行选型。 1.1 国内场景:Kimi K2.6 对于数据需境内处理或存在私有化部署需求的场景&#xff0c…...

机器学习评价指标之综合指标的关系

综合指标的关系宏平均考虑每个类别的个别表现,并对它们的评价指标(比如准确率、召回率等)进行平均。每个类别 被视为同等重要,无论类别的大小或样本数量。微平均则关注整体表现,它将所有类别的预测结果合并起来&#x…...

红黑树完全指南:从五条性质到完整插入删除实现

引言在前面的树系列中,我们学习了二叉搜索树(BST)和 AVL 树。AVL 树通过严格的平衡条件(|BF| ≤ 1)保证 O(log n) 的性能,但代价是删除操作可能触发 O(log n) 次旋转。红黑树(Red-Black Tree&am…...

10个sd-webui-regional-prompter实用技巧:从基础分割到高级2D区域配置

10个sd-webui-regional-prompter实用技巧:从基础分割到高级2D区域配置 【免费下载链接】sd-webui-regional-prompter set prompt to divided region 项目地址: https://gitcode.com/gh_mirrors/sd/sd-webui-regional-prompter sd-webui-regional-prompter是一…...

混合专家MoE拆解:GPT-4、千问、DeepSeek为什么都选这个架构

去年我写了个小模型做文本分类,全部参数只有1.5B,单卡就能跑。结果效果还行,但跟大模型比就是被吊打。 我就想,为什么那些几百B甚至上T参数的大模型,推理速度没比我的小模型慢一万倍? 答案就在MoE&#x…...

创业公司如何利用 Taotoken 统一管理多个 AI 模型服务

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 创业公司如何利用 Taotoken 统一管理多个 AI 模型服务 对于资源有限的创业团队而言,快速验证产品想法、迭代功能是生存…...

WireUI颜色选择器和日期选择器:提升用户体验的利器 [特殊字符][特殊字符]

WireUI颜色选择器和日期选择器:提升用户体验的利器 🎨📅 【免费下载链接】wireui TallStack UI components 项目地址: https://gitcode.com/gh_mirrors/wi/wireui WireUI颜色选择器和日期选择器是Laravel Livewire应用中提升用户体验的…...

为内部知识问答系统构建基于多模型聚合的智能回复引擎

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 为内部知识问答系统构建基于多模型聚合的智能回复引擎 在构建面向企业内部的智能知识问答系统时,一个核心挑战是如何在…...

互联网大厂 Java 求职面试实战:音视频场景中的技术挑战

互联网大厂 Java 求职面试实战:音视频场景中的技术挑战在这个互联网飞速发展的时代,越来越多的求职者走进了大厂的面试现场。今天,我们将跟随一位搞笑的程序员燕双非,来看看他在面试中的表现,以及他如何应对各种技术问…...

Rufus技术演进:从Windows 7告别到现代USB启动盘工具的重构之路

Rufus技术演进:从Windows 7告别到现代USB启动盘工具的重构之路 【免费下载链接】rufus The Reliable USB Formatting Utility 项目地址: https://gitcode.com/GitHub_Trending/ru/rufus 在开源工具生态中,技术栈的更新换代往往伴随着兼容性的艰难…...

【收藏干货】2026年AI Coding全面爆发!程序员终极职业升级攻略,告别被替代焦虑

2026年,AI编码技术迎来规模化落地爆发期,行业彻底告别“人工纯编码”的传统模式。对于所有程序员而言,当下最核心的生存与发展策略,早已不是埋头敲代码,而是从“被动写代码的执行者”全面升级为“主动驾驭AI的价值创造…...

MySQL高频面试题-02

这一篇的主题:日志双写机制、深分页瓶颈,以及死锁怎么查。上次和大家聊了 B 树和 MVCC,今天这篇我们直接上硬菜。在社招或者大厂面试中,面试官往往不满足于只问你“什么是索引”,他们更喜欢切入高并发、大数量、分布式的真实场景。…...

MySQL 高频面试题-01

在去面试之前,很多人天天背“八股文”,结果一到现场被面试官稍微一变形就问懵了。比如:“你天天说 B 树,那为什么不用 B 树?不用红黑树?它俩到底差在哪?”“既然索引能加速,那我把所…...

Structured3D完整指南:如何用3D结构化数据轻松构建智能室内场景

Structured3D完整指南:如何用3D结构化数据轻松构建智能室内场景 【免费下载链接】Structured3D [ECCV20] Structured3D: A Large Photo-realistic Dataset for Structured 3D Modeling 项目地址: https://gitcode.com/gh_mirrors/st/Structured3D 如果你正在…...