内容简介:现在大型的前端项目中是很需要注意可维护性,易读性的,因此选择使用“安全的” 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 没有类型检查
可以通过分离 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"' 复制代码可选的 props 导致的编译错误
为什么?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 类型的类型(二)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
互联网产品运营:产品经理的10堂精英课
丁华、聂嵘海、王晶 / 电子工业出版社 / 2017-5 / 59
《互联网产品运营:产品经理的10堂精英课》共有10章,前9章分别从互联网产品运营的9个点入手,最后一章辅以案例,分析当下市场热门产品的运营模式。 第1章点明在运营产品之前需要经过缜密的策划,这样才能有明确的运营方向;第2章讲述产品运营的定位,有了准确的定位,运营才不会走偏;第3章描述用户运营,用户是一款产品的根本,没有用户,产品就是死的;第4章讲述内容运营的技巧,产品内容要怎么运营才能受到用......一起来看看 《互联网产品运营:产品经理的10堂精英课》 这本书的介绍吧!