Vue3+TS项目---实用的复杂类型定义总结
namespace
概念
在TypeScript中,namespace是一种用于组织代码得结构,主要用于将相关得功能(例如类、接口、函数等)组合在一起。它可以帮助避免命名冲突,尤其是在大项目中。
用法
1.定义命名空间
使用namespace关键字定义一个命名空间,并在其中包含类、接口、函数等等。以下举例是我在项目中定义得接口参数类型,因为我得接口参数类型是放在一个文件中进行维护得,所以难免会出现相同参数名不同类型得情况出现。所以这里可以使用namaspace来定义不同模块下得接口参数类型。
declare namespace Api {namespace Auth {type systemInfo = {logo: string;systemName: string;nickname: string;avatar: string;email: string;tenantId: string;}type Domain = {domainName: string;}}
}
2.访问命名空间中的成员
需要使用命名空间名来访问其成员,使用.操作符。
/*** 获取系统名称,logo等信息* @param domainName*/
export function fetchPostSystemInfo(params?: Api.Auth.Domain){return request<Api.Auth.systemInfo>({url: 'xxxxx',method: 'get',params})
}
以上举例限制fetchPostSystemInfo异步请求中传去的参数params的类型约束是Api.Auth.Domain,
调用时通过request<Api.Auth.systemInfo>
明确指定响应数据类型是Api.Auth.systemInfo,确保调用者可以在代码中获得类型提示和安全的类型检查。
3.使用
const systemInfo:Api.Auth.systemInfo = reactive({logo: '',systemName: '',nickname: '',avatar: '',email: '',
})async function getSystemInfo() {const { data, error } = await fetchPostSystemInfo({ domainName: window.location.hostname });if (!error && data) {Object.assign(systemInfo, data);}
}
类型定义扩展
泛型类型
实例1
declare namespace Api {namespace Auth {type emailToken<T = any> = {email: string;} & T;}
}
这段代码定义了一个泛型类型emailToken,它由一个对象组成,包含一个名为email的字符串属性,并且可以通过泛型参数T扩展。T默认是any类型。
具体含义是:
- emailToken<T = any >:这是一个泛型类型定义,其中T是一个可选的泛型参数,默认值是any。如果你在使用时不传入T,则T的类型会是any。
- { email : string } & T:这表示emailToken 类型是由两个部分组成的对象类型:
-
- 一个固定的属性email,类型是string
- 通过& T,可以扩展其他属性,这些属性来源T。也就是说,emailToken是一个包含email属性的对象,并且可以包含任何你传入的T类型的属性
举例如下:
type CustomToken = emailToken<{token: string }>;
// CustomToken 类型为 { email: string, token: string }
在上面的例子中,CustomToken类型包含两个属性:email和token,其中email是固定的,而token是通过传入T定义的。
使用:
/*** 获取验证码* @param email* return string*/
export function fetchGetEmailToken(params?: Api.Auth.emailToken) {return request<string>({url: '/usercenter/api/uc/otp/request/email',method: 'post',)}
}let emailToken: string = '';
async function getEmailToken(email: string) {const { data: token, error } = await fetchGetEmailToken({ email });if (!error && token) {emailToken = token || '';window.$message?.success?.('验证码发送成功')return emailToken;}
}
实例2
type Response<T = unKnown> = {statusCode: number;message: string;success: boolean;timestamp: string;result: T
}
- 泛型T:
-
- Response是一个泛型类型,接受一个类型参数T,默认值为unknowm。
- T可以是任何类型,允许Response在使用时具有灵活性
- 属性
-
- statusCode: string; :表示后端服务的请求状态码,例如 401,200
message: string;
:表示后端服务的响应消息,提供对状态的更详细说明。- result: T; :表示响应的具体数据,类型为T。这允许Response用于多种数据结构
示例1 返回简单数据
const simpleResponse:Response<string> = {statusCode: 200,message: "request is success",timestamp: "1729159210638",success: true,result: "Some string data"
}
在这个例子中,result是一个字符串
示例2 返回对象数据
type User = {id:number;name:string;
}
const userResponse:Response<User> = {statusCode: 200,message: "request is success",timestamp: "1729159210638",success: true,result: {id: 1,name: 'Hzz'}
}
在这个例子中,data是一个User类型的对象
示例3 返回数组数据
cosnt usersResponse: Response<User []> = {statusCode: 200,message: "request is success",timestamp: "1729159210638",success: true,result:[{ id: 1, name: "Alice" },{ id: 2, name: "Bob" }]
}
这里,data是一个User对象的数组
扩展用法
可以通过不同的方式扩展Response类型,以适应更复杂的需求。
添加分页功能
假设你希望响应支持分页,可以扩展Response来包括分页信息:
type PaginatedResponse<T> = {items: T[];total: number;
}type Response<T = unknowm> = {statusCode: number;message: string;success: boolean;timestamp: string;result: PaginatedResponse<T>; // 包含分页信息
}
type User = {id:number;name:string;
}
// 使用示例
const paginatedUserResponse:Response<User> = {statusCode: 200,message: "request is success",timestamp: "1729159210638",success: true,result:{items:[{id: 1, name: "Alice"},{id: 1, name: "Alice"}],total: 2}
}
结合错误信息
如果你希望在失败的情况下包含错误信息,可以扩展响应结构:
type ErrorResponse = {errorCode: string;errorDetails?: string;
}type Response<T = unknown> = {statusCode: number;message: string;success: boolean;timestamp: string;result?: T; // result是可选的error?: ErrorResponse;
}const errorResponse: Response = {statusCode: 200,message: "request is success",timestamp: "1729159210638",success: true,error:{errorCode: '404',errorDetails: "The user with the specified ID does not exist.",}
}
总结:
- Response是一个灵活的泛型类型,用于描述后端服务的响应,包括状态、消息和具体数据
- 通过将T用于result属性,可以轻松适应不同的数据结构
映射类型
declare module "@elegant-router/types" {export type RouteLayout = "base" | "blank" | "baseVariant";/*** route map*/export type RouteMap = {"root": "root";"403": "/403";"404": "/404";"500": "/500";"application": "/application";"application_develop": "/application/develop";"client": "/client";};/*** route key*/export type RouteKey = keyof RouteMap;/*** route path*/export type RoutePath = RouteMap[RouteKey];/*** custom route key*/ export type CustomRouteKey = Extract<RouteKey,| "root"| "not-found"| "exception"| "exception_403"| "exception_404">;
}
以上定义类型主要用来描述路由映射和键、值得类型,详细解析如下:
RouteMap
类型 是一个对象,它描述了路由得命名和对应关系
RouteKey
类型
- keyof 操作符用于获取某个类型得键的集合
- 在这里,keyof RouteMap将会提取RouteMap中所有的键,形成一个联合类型,也 就是
"403" | "404 | "500" | "application" | "application_develop" | "client"
。
因此,RouteKey
类型将会是:
type RouteKey = "403" | "404" | "500" | "application" | "application_develop" | "client";
在实际开发中常用于确保路由键与路由路径的映射是安全的和类型化的。例如,使用RouteKey
来引用某个路由时,TypeScript会确保你只能使用定义过的路由键,避免拼写错误等问题。
RoutePath
类型
在TypeScript中,使用方括号[]可以通过索引访问对象类型的值,语法如下:
T[K]
- T是一个对象类型
- K是T的键(可以是单个键或者键的联合类型)
通过T[k]这种索引访问方式,可以获取T中键K对应的值的类型。如果K是联合类型,结果会是所有键对应值的联合类型。
因此,在 exporttypeRoutePath = RouteMap[RouteKey]; 中
RouteMap
是一个对象类型 ,它的键是RouteKey,即 "403" | "404" | "500" | "application" | "application_develop" | "client" ,对应的值的路径字符串是对象的值,RouteMap[RouteKey]
会返回 RouteMap 中键的值的类型
RouteMap["root"] // "/"
RouteMap["403"] // "/403
...
最终结果:
type RoutePath = "/" | "/403" | "/404" | "/500" | "/application" | "/application/develop" | "/client";
总结:这种用法可以在需要动态获取某些键对应值的场景中确保类型安全,比如在路由系统中确保路径类型和路由键的一致性。
Exclude
类型工具
Exclude<T, U>是TypeScript内置的条件类型,它用于从类型T中排除那些可以分配给类型U的成员。它的定义是:
type Exclude<T, U> = T extends U ? never : T;
- 如果T中某个类型能够分配给U(T extends U 为 true),那么返回never类型(表示排除该成员)
- 否则,返回T本身
分析以下类型结果:
const RouteKey = "403" | "root" | "not-found" | "application" | "application_develop" | "client"; | "/client";
type I18nRouteKey = Exclude<RouteKey, 'root' | 'not-found'>;const RouteKey1 = 'root' | 'not-found'
type I18nRouteKey1 = Exclude<RouteKey1, 'root' | 'not-found'>;
I18nRouteKey:
- 从
RouteKey
中排除 'root' | 'not-found' 这两个键 - 那么 I18nRouteKey的最终结果是:type I18nRouteKey = "403" | "application" | "application_develop" | "client"; | "/client";
I18nRouteKey1:
- 从
RouteKey1
中排除 'root' | 'not-found' 这两个键 - 那么 I18nRouteKey1的最终结果是 type I18nRouteKey1 = never
结论:
I18nRouteKey1 的结果是never,是因为 因为 RouteKey1
中只有 "root"
和 "not-found"
。
当 RouteKey 中有其他键时, I18nRouteKey 会成为这些剩余键的联合类型。
Omit
工具类型
Omit<T, K>
是 TypeScript的内置工具类型,用于从类型T中排除指定的键K。
- T:要修改的原始类型
- K:要排除的键,可以是单个键或者多个键的联合类型
举例说明:
定义Breadcrumb结构
interface Menu {key: string;// 唯一标识符,用于识别菜单项label: string;// 显示给用户的菜单项标签i18nKey?: I18n.I18nKey | null;// 可选的国际化键,用于多语言支持routeKey: RouteKey;// 路由的键,表示该菜单项对应的路由routePath: RoutePath;// 路由的路径,指向该菜单项的具体路径icon?: () => VNode;// 可选的图标,返回一个虚拟节点(通常用于渲染图标)children?: Menu[];// 可选的子菜单项,数组类型,表示该菜单项下的子菜单
}type Breadcrumb = Omit<Menu, 'children'> & {options?: Breadcrumb[];
}
解释:
Omit<Menu, 'children'>
: 使用Omit工具类型从Menu接口中排除children属性。这样,Breadcrumb不会直接包含children。- & { options?: Breadcrumb[]; }:通过交叉类型将Omit的结果与一个新对象类型结合,这个新类型包含一个可选的属性options,其类型为Breadcrumb[],表示该面包屑导航项包含其他Breadcrumb对象的数组
Breadcrumb
的最终结构
type Breadcrumb = {key: string;// 继承自 Menulabel: string;// 继承自 Menui18nKey?: I18n.I18nKey | null;// 继承自 MenurouteKey: RouteKey;// 继承自 MenuroutePath: RoutePath;// 继承自 Menuicon?: () => VNode;// 继承自 Menuoptions?: Breadcrumb[]; // Breadcrumb[];
}
用法示例
假设我们要构建一个面包屑导航,可以使用Breadcrumb类型如下:
const breadcrumn:Breadcrumb = {key: "home",label: "Home",routeKey: "root",routePath: "/",icon: () => <span>🏠</span>, //可选的图标,返回一个虚拟节点options:[{key: "about",label: "About us",routeKey: "about",routePath: "/about"icon: () => <span>ℹ️</span>, // 子面包屑的图标options: [//....]},{key: "contact",label: "Contact",routeKey: "contact",routePath: "/contact",icon: () => <span>📞</span>, // 子面包屑的图标}]
}
说明
key
、label
、routeKey
和routePath
属性是必需的,定义了面包屑项的基本信息。icon
属性是一个可选的函数,返回一个虚拟节点(这里使用了简单的 Emoji 作为示例图标)。options
属性用于定义子面包屑项,支持嵌套结构。
相关文章:
Vue3+TS项目---实用的复杂类型定义总结
namespace 概念 在TypeScript中,namespace是一种用于组织代码得结构,主要用于将相关得功能(例如类、接口、函数等)组合在一起。它可以帮助避免命名冲突,尤其是在大项目中。 用法 1.定义命名空间 使用namespace关键…...
尚硅谷rabbitmq2024 工作模式路由篇 第11节 答疑
String exchangeName "test_direct"; /! 创建交换机 人图全 channel.exchangeDeclare(exchangeName,BuiltinExchangeType.DIREcT, b: true, b1: false, b2: false, map: null); /1 创建队列 String queue1Name "test_direct_queue1"; String queue2Name &q…...

HTTP vs WebSocket
本文将对比介绍HTTP 和 WebSocket ! 相关文章: 1.HTTP 详解 2.WebSocket 详解 一、HTTP:请求/响应的主流协议 HTTP(超文本传输协议)是用于发送和接收网页数据的标准协议。它最早于1991年由Tim Berners-Lee提出来&…...

R语言医学数据分析实践-数据读写
【图书推荐】《R语言医学数据分析实践》-CSDN博客 《R语言医学数据分析实践 李丹 宋立桓 蔡伟祺 清华大学出版社9787302673484》【摘要 书评 试读】- 京东图书 (jd.com) R语言编程_夏天又到了的博客-CSDN博客 R编程环境的搭建-CSDN博客 在分析公共卫生数据时,数…...
JavaWeb环境下Spring Boot在线考试系统的优化策略
摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了基于JavaWeb技术的在线考试系统设计与实现的开发全过程。通过分析基于Java Web技术的在线考试系统设计与实现管理的不足,创建了一个计算机管理基于Ja…...

ETL技术在金蝶云星空与旺店通WMS集成中的应用
金蝶云星空数据集成到旺店通WMS的技术案例分享 在数字化转型的背景下,现代企业对系统间的数据集成需求日益增加。本篇文章将以“组装入库>其他入库单-1”方案为例,详细解析如何通过轻易云数据集成平台,实现金蝶云星空与旺店通WMS之间的数…...
【力扣热题100】3194. 最小元素和最大元素的最小平均值【Java】
题目:3194.最小元素和最大元素的最小平均值 你有一个初始为空的浮点数数组 averages。另给你一个包含 n 个整数的数组 nums,其中 n 为偶数。 你需要重复以下步骤 n / 2 次: 从 nums 中移除 最小 的元素 minElement 和 最大 的元素 maxElement…...

机器学习拟合过程
import numpy as np import matplotlib.pyplot as plt# 步骤1: 生成模拟数据 np.random.seed(0) X 2 * np.random.rand(100, 1) y 4 3 * X 2 * X**2 np.random.randn(100, 1)# 步骤2: 定义线性模型 (我们从随机权重开始) w np.random.randn(2, 1) b np.random.randn(1)#…...

如何快速部署一套智能化openGauss测试环境
一、openGauss介绍 openGauss是一款开源关系型数据库管理系统,采用木兰宽松许可证v2发行,允许用户自由地复制、使用、修改和分发软件。openGauss内核深度融合了华为在数据库领域多年的研发经验,结合企业级场景需求,持续构建竞争力…...
【设计模式】深入理解Python中的原型设计模式
深入理解Python中的原型设计模式 在软件开发中,有时需要创建对象的过程非常复杂或者代价较高,而在同一类对象的实例之间有很多重复的属性。为了避免重复构造对象,提升性能和效率,原型设计模式(Prototype Pattern&…...
Django CORS配置方案
参考 https://pypi.org/project/django-cors-headers/ 在setting.py中设置 INSTALLED_APPS [......corsheaders, #添加此行 ]MIDDLEWARE[......corsheaders.middleware.CorsMiddleware, #添加此行django.middleware.common.CommonMiddleware,#django.middleware.csrf.CsrfVi…...

2024年开放式耳机哪个牌子好?推荐最好的顶级开放式耳机品牌
在当下,开放式耳机逐渐成为众多消费者的新宠。与传统入耳式耳机相比,开放式耳机展现出诸多独特之处。它可以呈现出更清晰的音质效果,让用户有更美妙的听觉体验。在佩戴感上,开放式耳机更为舒适,不会给耳朵带来压迫感。…...

零基础读懂Stable Diffusion!
前言 一文搞懂Stable Diffusion是什么,怎么训练和使用,语义信息影响生成图片的过程。>>[][加入极市CV技术交流群,走在计算机视觉的最前沿] 前几个月AIGC可谓是大热了一把,各种高质量的生成图片层出不穷,而其中…...
Hash Join 和 Index Join工作原理和性能差异
在数据库查询中,Hash Join 和 Index Join 是两种常见的表连接策略。了解它们的工作原理和性能差异有助于设计高效的数据库查询。我们可以使用 Java 模拟这两种不同的连接方式,并进行性能对比。 1. Hash Join 和 Index Join 的概念: Hash Joi…...
Apifox简介及使用
Apifox 是一款集 API文档管理、接口调试、接口自动化测试 和 Mock 功能于一体的全功能工具,旨在为开发者和测试人员提供一个高效的一站式解决方案。它融合了 Postman、Swagger、JMeter 等工具的优势,能够极大地提升团队协作和 API 开发的效率。 在实际开…...
十、IPD 实施细节(产品设计与开发管理)
产品设计与开发管理 产品设计与开发管理是IPD(集成产品开发)实施过程中的核心环节。它确保从概念设计到最终产品的实现能够按照预定的质量、成本、进度目标顺利完成,并与市场需求、技术发展及企业战略保持一致。IPD强调产品设计与开发管理过程中跨职能团队的协作、流程的系…...

MySQL-13.DQL-聚合函数
一.DQL-分组查询 二.聚合函数 -- DQL:分组查询 -- 聚合函数 -- 1.统计该企业员工数量 count select count(id) from tb_emp; select count(job) from tb_emp;select count(A) from tb_emp; select count(*) from tb_emp;-- 2.统计该企业最早入职的员工 min select min(entr…...
为什么跟别人学习如何证明定理要远比使用定理更有意义
目录 背景 为什么跟别人学习 什么是高人,如何判断 高人定义 如何判断一个人的能力? 如何考量一个人的成就? 只知道使用定理的局限性 1. 缺乏灵活性和适应性 2. 无法创新或拓展新方法 3. 容易误用或误解定理 4. 难以推理和分析复杂问…...
Qt在Win,Mac和Linux的开机自启设置
Windows Windows 使用注册表来管理开机自启的应用程序。 void runWithSystem(const QString& name, const QString& path, bool autoRun) {QSetting reg("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSetting::NativeForma…...

spring boot热部署
使用热部署解决了每次都需要重新启动的问题,但不过热部署的在对于改动比较小时速度可能快一些,改动大的话尽量停止 1.使用热部署之前需要在pom.xml文件中导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifa…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...