内容简介:现在大型的前端项目中是很需要注意可维护性,易读性的,因此选择使用“安全的” JavaScript -- 即 Typescript 是非常有帮助的,你工作将会变得更简单,避免一些潜在的错误问题。Typescript 搭配 React 能轻松的创建你的应用,配置好 tsconfig.json,那么 Typescript 就会指导你写出健壮的代码。一切都是那么顺利,直到你遇到一个“大的”问题--处理组件中的作者在 github 上发布了这篇文章是基于 TypeScript 2.9 版本以及开启严格模式进行的。我将
现在大型的前端项目中是很需要注意可维护性,易读性的,因此选择使用“安全的” JavaScript -- 即 Typescript 是非常有帮助的,你工作将会变得更简单,避免一些潜在的错误问题。Typescript 搭配 React 能轻松的创建你的应用,配置好 tsconfig.json,那么 Typescript 就会指导你写出健壮的代码。一切都是那么顺利,直到你遇到一个“大的”问题--处理组件中的 defaultProps
作者在 github 上发布了 rex-tils 代码库,其中包含了这篇文章讨论的解决办法
这篇文章是基于 TypeScript 2.9 版本以及开启严格模式进行的。我将会演示这个问题以及组件中怎么解决它
一个 Button 组件
我们开始定义一个 Button 组件,遵循以下的 API 实现:
Button API:
- onClick (点击事件)
- color (定义按钮颜色)
- type (按钮的类型有 ‘button’ 或者 ‘submit’) 我们将 color 和 type 定义为可选项,用 defaultProps 定义他们的默认值(组件的使用者可能不会添加这些参数)
import {MouseEvent, Component} from 'react'; import * as React from 'react'; type Props = { onClick(e: MouseEvent<HTMLElement>): void; color?: 'blue' | 'green' | 'red'; type?: 'button' | 'submit'; } class Button extends Component<Props> { static defaultProps = { color: 'blue', type: 'button' }; render() { const {onClick: handleClick, color, type, children} = this.props; return ( <button type={type} style={{color}} onClick={handleClick} > {children} </button> ); } } export default Button; 复制代码
Button 组件实现
现在,当我们在其他组件中使用 Button 时,编辑代码就能获取到相关的提示(可选项,必传的 Props)
但是,Button 组件的 defaultProps 属性没有被检查,因为类型检查器不能从泛型类扩展定义的静态属性中推断它的类型。
具体的解释:
static defaultProps
可以通过分离 Props 提取出 color 和 type 的属性,然后用类型交叉把默认值映射为可选值。后面这步通过 TS 标准库中 Partial 类型来快速实现。
然后显示地指定 defaultProps 的类型是 DefaultProps
,这样检查器就能检查 defaultProps。
我倾向于使用下面的方法,就是提取 defaultProps 和 initialState (如果组件有 state)来分离状态类型,这样做另外的好处——从实现里面可以获取类型的明确定义,减少了定义 props 的模板,只保留核心必选的功能。
接下来在组件里面加入一点复杂的逻辑。 需求是,不希望只使用 css 内嵌样式(这是反 设计模式 以及性能糟糕的),而是能基于 color 属性,生成具有一些预定义的 css 类。
定义了 resolveColorTheme
函数,接受 color 的参数,返回自定义的 className。
但是,像上面那样会有一个编译错误的!
TS Error: Type 'undefined' is not assignable to type '"blue" | "green" | "red"' 复制代码
为什么?color 是可选的,编译启用的是严格模式,而联合类型扩展存在 undefined/void 类型,但是函数不接受 undefined。
怎么修复这个价值很高的问题呢?
TypeScript 2.9 中提供了 4 中方法修复它:
- 非空断言语句(Non-null assertion operator)
- 组件类型重置(Component type casting)
- 高阶组件定义 defaultProps
- Props getter 函数
1. 非空断言语句
这个方法是显而易见的,就是明确告诉类型检查器,这不会是 null 或者 undefined,通过 !
操作符实现:
对于简单的用例(props 属性很少的,仅在 render 方法接受特定的 props 的用例)这样做没问题的,随着业务的增长,这样的方法会加剧你组件的混乱,不可读。你需要花费大量时间检查哪个 props 被定义为 defaultProps,占用了开发者大量时间,这样也容易导致错误
2. 组件类型重置
那么怎么解决上一种问题的局限性呢?我们通过创建一个匿名类,断言它的类型为组合类型,设置 defaultProps 单个的类型(以及只读类型限制),如下:
这能解决我们当前的问题,但感觉是怪异的。
在 TypeScript 2.8 版本介绍了一种高级类型- 条件类型(conditional types)
T extends U ? X : Y // 表示 T 如果继承自 U,那么它的类型就是 X,否则就是 Y 复制代码
3. 高阶函数定义 defaultProps
定义一个工厂函数/高阶函数,用于 defaultProps 和 条件类型的 props 合并。
其中 withDefaultProps 就是一个高阶函数,使用它,你不用明确地使用 React 的接口定义 defaultProps,另外如果不需要检查 defaultProps,可以删除上面代码中 type DefaultProps
。 但是要注意,它不能用于泛型组件,像这样:
createPropsGetter 函数创建了一个闭包,通过泛型参数存储/推断出 defaultProps 类型。然后该函数返回了带有 defaultProps 的 props,从 TS 运行时角度看,它返回的 props 和我们传递的是相同的,因此 React 标准的 API就能获取运行时 props 的获取/解析。 如下实现:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- golang对自定义类型进行排序的解决方法
- springboot接收Date类型数据异常与解决办法
- Gson格式转换Integer变为Double类型问题解决 原 荐
- golang的值类型,指针类型和引用类型&值传递&指针传递
- Scala 类型的类型(三)
- Scala 类型的类型(二)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
我知道他想看什么
沙建军 / 中信出版社 / 2018-1 / 48.00
社交媒体迅速发展、信息快速迭代、时间碎片化;大数据、智能终端、物联网横空出世;移动支付、网红经济和传统营销失效,这些都让这个时代的媒体、内容、渠道、产品之间的边界越来越模糊,也从根本上改变了营销的逻辑,内容营销从热词变成趋势,变成营销的底层思维。未来一切都是媒体,形式也是内容。 本书作者通过对国内外36个内容营销的新近案例的故事化描述和透彻分析,提出“组织媒介化”“营销内容化”“内容情趣化”......一起来看看 《我知道他想看什么》 这本书的介绍吧!