前言
大家好,我是HoMeTown
前段时间用TS
做了一个线上标准的项目,也都提测了,最近可以抽时间来整理一下项目中用到的技术栈,( 我用前端【最新】技术栈完成了一个生产标准的项目【Vue3 + TS + Vite + Pinia + Windicss + NavieUI】。今天聊一聊TypeScript
。
背景
因为是一个EPR系统,项目中包含了大量的计算与字段 & 秉持着操手前端最新技术栈 的目标,果断选择了TypeScript
,接下来,我就聊一下通过这个项目,我得到了哪些经验。
TypeScript
这个东西是什么,我就不过多阐述了,直接上干货!
构建一个类型的属性,书写类型要保持一致
举个🌰
// bad type UppercaseRole = 'ADMIN' | 'User' | 'guest' // good type UppercaseRole = 'ADMIN' | 'USER' | 'GUEST' type UppercaseRole = 'Admin' | 'User' | 'Guest' type UppercaseRole = 'admin' | 'user' | 'guest' 复制代码
泛型
不要重复的创建类型,提升泛型的复用性,举个🌰
type Add<T> = (a: T, b: T) => T const addNumbers: Add(number) = (a, b) => a + b const addStrings: Add(string) = (a, b) => a + b 复制代码
在上述的🌰中,我们通过泛型,定义一个类型,传入不同的类型即可,不需要给每一个函数都写一个类型,节省精力,简化代码。
实用类型
Pick<Type, Keys>
Pick
可以从现有的Type中挑选属性的集合 keys来创建一个新的类型,keys可以是一个字符串字面或者一个联合字符串。需要注意的是,Keys的值必须是Type的键。举个🌰
type UserInfo = { username: string; age: number; realname: string; email: string; phone: number; password: string; } // 使用Pick对你想提取的部分进行提取即可 type UserAccount = Pick<UserInfo, 'username' | 'password'> 复制代码
Omit<Type, Keys>
Omit
与Pick
相反,你传入的Keys
变成了你想要去掉哪些属性。举个🌰
type UserInfo = { username: string; age: number; realname: string; email: string; phone: string; password: string; } // 使用Omit对你不想要的属性进行剔除 type UserDescInfo = Pick<UserInfo, 'username' | 'password'> 复制代码
Partial< Type>
Partial
可以构造一个全都是可选属性的类型,具体的使用场景比如一些后端返回的无法具体确认的数据,举个栗子。
type OrderRowInfo = { orderId: number; orderCn: string; orderEn: string; orderDecs: string; remark: string; } type PartialOrderRowInfo = Partial<Type> // 它其实返回之后就是 orderId?: number; orderCn: string; ... 复制代码
Required< Type>
Required
与Partial
相反,举个栗子
type PartialOrderInfo = { orderId: number; orderCn: string; orderEn?: string; orderDesc?: string; remark?: string; } type RequireOrderInfo = Required(PArtialOrderInfo) 复制代码
Readonly< Type>
你可以理解 Readonly
是定义变量时的const
,只不过他是定义类型的。举个🌰
type User = { username: string; } type ReadOnlyUser = ReadOnly<User> const user: ReadOnlyUser = { username: 'HoMeTown' } user.username = 'handsome boy' // Cannot assign to 'username' because it is a read-only property 复制代码
操作符
可选链 ?.
可选链的出现让我感觉是真的太香了,终于不用再做 &&
这种操作了,有时候我们会处理一些深层及的obj,光做非空 !undefiend的判断就得写一堆堆,有了?.
,妈妈再也不用担心我写不好了。
举个🌰
type DeptMember { memberName: string; } type UserInfo = { username: string; dept: { deptname: string; deptMembers: DeptMember[] } } const res = await fetchGetUserInfo(userId) // before bad if(res && res.data && res.data.userInfo && res.data.userInfo.dept && res.data.userInfo.dept.deptMembers) { // do something... } // now good if(res?.data?.userInfo?.dept?.deptMembers) { // do something } 复制代码
空值合并 ??
当左侧操作数为 null
或 undefined
时,其返回右侧的操作数。否则返回左侧的操作数,与逻辑或||
操作符不同,逻辑或会在左操作数为 falsy 值时返回右侧操作数。也就是说,如果你使用 ||
来为某些变量设置默认的值时,你可能会遇到意料之外的行为。比如为 falsy 值(’’、NaN 或 0)时,举个🌰
// 使用 ?? const tem = 0 ?? '---'; console.log(tem); // 输出:0 // 使用 || const tem = 0 || '---'; console.log(tem); // 输出:'---' 复制代码
假设我们在一个table
组件中有某些数字类型的值需要展示,用||
的话如果API返回的是0
,那就展示错了。
逻辑空赋值 ??=
其实就是在进行 ??
操作后,进行一个赋值的动作
userInfo.age ??= 26 复制代码
这些就是我在开发的过程中比较常用到的,可能还有一点,以后想起来再补充。