‘any‘ is cheap, show me the ‘type‘(Ⅱ)

引子

之前的文中我们介绍了JS的灵活以及TS可以“管束”JS,那么TS是否能在“管束的同时”,还保留代码的灵活呢?

?的使用说起

?的使用可以极大的保持你的代码灵活,且避免xxx is not defined问题。举个例子,我们之前聊到的菜单组件,我希望点击每个菜单项时,如果当前菜单有绑定一个“onClick”方法就在每个菜单项点击时执行,没有则忽略,类似这样:

较好的做法就是把这个onClick作为一个Menu这个props的可选属性:

export interface MenuProps {
  onClick?:  (selectIndex: string) => void
  /**other props */
  // ...
}

如此一来当你在组件中需要处理onClick时,如果这个属性可能是undefined,Ts会提示你:

这样就可以在开发中专注业务,而将提示可能未处理xxx is not defined的工作交给TS,当然,这一切的前提是你对你的入参属性有清晰准确的定义。

使用&实现类型的联合,搭配Partial实现可选参数

我在上一篇文章中提到使用TS可以从定义入参的type和interface开始,还提到了一个问题,如何保证我们自己编写的button组件拥有onClick/onFocus等所有button的原生方法,以保证使用者可以无学习成本的使用它?全部实现一遍的方式过于麻烦,当然,button的原生属性、方法,React已经帮我们准备好了——ButtonHTMLAttributes,我们自定义的buttonProps只要全包含它即可,可以使用&, 当然,我们肯定希望这样添加过来的原生属性都是带?的可选属性,这样代码就更灵活了,很简单,使用Partial即可:

interface BaseButtonProps {
  /** 设置按钮样式 */
  className?: string
  /** 设置按钮禁用 */
  disabled?: boolean
  /** 设置按钮大小 */
  size?: buttonSize
  /** 设置按钮类型 */
  btnType?: buttonType
}
​
// 帮助当前Button组件获取诸如onClick方法等Button的原生属性,方法
type NativeButtonProps = BaseButtonProps & ButtonHTMLAttributes<HTMLElement>
// 将所有属性均变为可选的,通过Partial实现
export type ButtonProps = Partial<NativeButtonProps>

这样开发者使用时,就和原生button的使用体验一模一样了:

扫描二维码关注公众号,回复: 15794623 查看本文章

使用extends实现接口的继承,并通过Omit实现排除

刚才举的例子介绍了如何通过 &实现类型的“继承”,你是否会好奇,继承不是extends吗?

当然,也可以。

比如我们要开发Input组件,按上面说的思路,我们可以继承React的InputHTMLAttributes,完全可以这样写:

type InputSize = 'lg' | 'sm'
​
export interface InputProps extends InputHTMLAttributes<HTMLElement> {
    // 自定义属性
    /**
   * 设置input的size
   */
  size?: InputSize;
}

不过这样代码会报错,是因为InputHTMLAttributes中就有size这个属性了,当然你可以对你的自定义属性size重命名,亦或者,使用Omit“排除”这个属性,类似要求使用子类自身属性,而不继承父类特定属性的意思

继承到底有什么好

上面分享的一些TS技巧都是始自对函数/纯函数中输入属性的类型限定,进而实现代码中的编码提示,错误检查提示等。其实对一个函数/纯函数的输出,也可以限定。那就是通过ReturnType。很多类型,技巧,你也可以通过这里了解更多。

使用TS开发代码的体验就要不停地和类型死磕,这样的行为被称为:类型体操。如果你对这些类型的实现方式感兴趣,可以看看这里,也希望大家在这些磨砺后,可以喊出那句——

迎面向我们走来的,是OpenTiny方阵

我们今天介绍的&/extends都跟“继承”有点关系,那么,继承到底有什么好?

最简单的好处,他能减少你的重复代码,比如上面说的button组件中,通过继承React.ButtonHTMLAttributes无需实现onClick、onFocus等方法。当然,更广泛的说,很多复杂的组件,也是组合了多个简单组件,那他们的属性之间就一定可以通过继承来简化。比如一个AutoComplete组件,就是一个Input组件加一个Select组件。那它的props可能就是这样:

当然,你也可以把很多组件的公共属性抽取出来,这样可能还能进一步简化代码,类似这样的设计:

或者这样:

没错,这就是我们的TinyUI组件库,Angular版本的设计理念,如今TinyUI已经正式开源,你可以从这里了解更多~当然,也欢迎大家点个star,也欢迎微信搜索我们的小助手: opentiny-official,和我们更多地互动!

猜你喜欢

转载自blog.csdn.net/OpenTiny/article/details/128103423
me