内容简介:现在大型的前端项目中是很需要注意可维护性,易读性的,因此选择使用“安全的” 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 类型的类型(二)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Seasoned Schemer
Daniel P. Friedman、Matthias Felleisen / The MIT Press / 1995-12-21 / USD 38.00
drawings by Duane Bibbyforeword and afterword by Guy L. Steele Jr.The notion that "thinking about computing is one of the most exciting things the human mind can do" sets both The Little Schemer (form......一起来看看 《The Seasoned Schemer》 这本书的介绍吧!