TS项目开发过程中减少重复代码

对于上面的 get 和 post 方法,为了避免重复的代码,我们可以提取统一的类型签名:

type HTTPFunction = (url: string, opts: Options) => Promise;

const get: HTTPFunction = (url, opts) => { /* … */ };

const post: HTTPFunction = (url, opts) => { /* … */ };

对于 TypeScript 初学者来说,在定义接口的时候也要小心,避免出现以下类似的重复代码。比如:

interface Person {

firstName: string;

lastName: string;

}

interface PersonWithBirthDate {

firstName: string;

lastName: string;

birth: Date;

}

很明显,相对于 Person 接口来说,PersonWithBirthDate 接口只是多了一个 birth 属性,其他的属性跟 Person 接口是一样的。那么如何避免出现例子中的重复代码呢?要解决这个问题,可以利用 extends 关键字:

interface Person {

firstName: string;

lastName: string;

}

interface PersonWithBirthDate extends Person {

birth: Date;

}

当然除了使用 extends 关键字之外,也可以使用交叉运算符(&):

type PersonWithBirthDate = Person & { birth: Date };

下面我们来继续看另一个例子,假设你已经定义 State(代表整个应用程序的状态)和 TopNavState(只代表部分应用程序的状态)两个接口:

interface State {

userId: string;

pageTitle: string;

recentFiles: string[];

pageContents: string;

}

interface TopNavState {

userId: string;

pageTitle: string;

recentFiles: string[];

}

上述的 TopNavState 接口相比 State 接口只是缺少了 pageContents 属性,但我们却重复声明其他三个相同的属性。为了减少重复代码,我们可以这样做:

type TopNavState = {

userId: State[‘userId’];

pageTitle: State[‘pageTitle’];

recentFiles: State[‘recentFiles’];

};

在上面代码中,我们通过成员访问的语法来提取对象中属性的类型,从而避免重复定义接口中相关属性的类型。但这并没有解决本质的问题,我们还有很大的优化空间。针对这个问题,我们可以利用映射类型来进一步做优化:

type TopNavState = {

};

鼠标悬停在 TopNavState 显示它的声明,实际上,这个定义与前一个定义完全相同。

通过映射类型优化后的代码,相比 TopNavState 接口最初的代码简洁了许多。那还有没有优化空间呢?其实是有的,我们可以利用 TypeScript 团队为我们开发者提供的工具类型,这里我们可以使用 Pick

type TopNavState = Pick<

State, ‘userId’ | ‘pageTitle’ | ‘recentFiles’

;

其实除了 Pick 之外,在实际开发过程我们还可以利用其他内置的工具类型来减少重复代码。这里我们再来介绍另一个比较常用的工具类型,即 Partial。以下是未使用 Partial 的例子:

interface Options {

width: number;

height: number;

color: string;

label: string;

}

interface OptionsUpdate {

width?: number;

height?: number;

color?: string;

label?: string;

}

class UIWidget {

constructor(init: Options) {

/* … */

}

update(options: OptionsUpdate) {

/* … */

}

}

在以上示例中,我们定义了 Options 和 OptionsUpdate 两个接口,它们分别用于描述 UIWidget 的初始化配置项和更新配置项。相比初始化配置项,更新配置项的所有属性都是可选的。

现在我们来开始优化上述的代码,我们先来看一下不使用 Partial 的情形:

type OptionsUpdate = {[k in keyof Options]?: Options[k]};

keyof 操作符接受一个类型,并返回一个由 key 组成的联合类型:

type OptionsKeys = keyof Options;

// Type is “width” | “height” | “color” | “label”

而 in 操作符是用来遍历枚举类型或联合类型。接着,我们来看一下使用 Partial 的情形:

class UIWidget {

constructor(init: Options) { /* … */ }

update(options: Partial) { /* … */ }

}

总结

  • 框架原理真的深入某一部分具体的代码和实现方式时,要多注意到细节,不要只能写出一个框架。

  • 算法方面很薄弱的,最好多刷一刷,不然影响你的工资和成功率😯

  • 在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。

  • 要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!

喜欢这篇文章文章的小伙伴们点赞+转发支持,你们的支持是我最大的动力!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值