【译】React, TypeScript 中 defaultProps 的类型解决

栏目: IOS · Android · 发布时间: 4年前

内容简介:现在大型的前端项目中是很需要注意可维护性,易读性的,因此选择使用“安全的” 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)

【译】React, TypeScript 中 defaultProps 的类型解决

但是,Button 组件的 defaultProps 属性没有被检查,因为类型检查器不能从泛型类扩展定义的静态属性中推断它的类型。

具体的解释:

static defaultProps
【译】React, TypeScript 中 defaultProps 的类型解决
默认的 props 没有类型检查

可以通过分离 Props 提取出 color 和 type 的属性,然后用类型交叉把默认值映射为可选值。后面这步通过 TS 标准库中 Partial 类型来快速实现。

然后显示地指定 defaultProps 的类型是 DefaultProps ,这样检查器就能检查 defaultProps。

【译】React, TypeScript 中 defaultProps 的类型解决
组件的 defaultProps 属性类型检查的实现

我倾向于使用下面的方法,就是提取 defaultProps 和 initialState (如果组件有 state)来分离状态类型,这样做另外的好处——从实现里面可以获取类型的明确定义,减少了定义 props 的模板,只保留核心必选的功能。

【译】React, TypeScript 中 defaultProps 的类型解决

接下来在组件里面加入一点复杂的逻辑。 需求是,不希望只使用 css 内嵌样式(这是反 设计模式 以及性能糟糕的),而是能基于 color 属性,生成具有一些预定义的 css 类。

定义了 resolveColorTheme 函数,接受 color 的参数,返回自定义的 className。

【译】React, TypeScript 中 defaultProps 的类型解决

但是,像上面那样会有一个编译错误的!

TS Error:
Type 'undefined' is not assignable to type '"blue" | "green" | "red"'
复制代码
【译】React, TypeScript 中 defaultProps 的类型解决
可选的 props 导致的编译错误

为什么?color 是可选的,编译启用的是严格模式,而联合类型扩展存在 undefined/void 类型,但是函数不接受 undefined。

怎么修复这个价值很高的问题呢?

TypeScript 2.9 中提供了 4 中方法修复它:

  • 非空断言语句(Non-null assertion operator)
  • 组件类型重置(Component type casting)
  • 高阶组件定义 defaultProps
  • Props getter 函数

1. 非空断言语句

这个方法是显而易见的,就是明确告诉类型检查器,这不会是 null 或者 undefined,通过 ! 操作符实现:

【译】React, TypeScript 中 defaultProps 的类型解决
在 render 方法中使用非空断言语句

对于简单的用例(props 属性很少的,仅在 render 方法接受特定的 props 的用例)这样做没问题的,随着业务的增长,这样的方法会加剧你组件的混乱,不可读。你需要花费大量时间检查哪个 props 被定义为 defaultProps,占用了开发者大量时间,这样也容易导致错误

2. 组件类型重置

那么怎么解决上一种问题的局限性呢?我们通过创建一个匿名类,断言它的类型为组合类型,设置 defaultProps 单个的类型(以及只读类型限制),如下:

【译】React, TypeScript 中 defaultProps 的类型解决

这能解决我们当前的问题,但感觉是怪异的。

在 TypeScript 2.8 版本介绍了一种高级类型- 条件类型(conditional types)

T extends U ? X : Y
// 表示 T 如果继承自 U,那么它的类型就是 X,否则就是 Y
复制代码

3. 高阶函数定义 defaultProps

定义一个工厂函数/高阶函数,用于 defaultProps 和 条件类型的 props 合并。

【译】React, TypeScript 中 defaultProps 的类型解决

其中 withDefaultProps 就是一个高阶函数,使用它,你不用明确地使用 React 的接口定义 defaultProps,另外如果不需要检查 defaultProps,可以删除上面代码中 type DefaultProps 。 但是要注意,它不能用于泛型组件,像这样:

【译】React, TypeScript 中 defaultProps 的类型解决
你在泛型组件上使用了高阶函数(withDefaultProps 函数),会导致它的泛型丢失,

createPropsGetter 函数创建了一个闭包,通过泛型参数存储/推断出 defaultProps 类型。然后该函数返回了带有 defaultProps 的 props,从 TS 运行时角度看,它返回的 props 和我们传递的是相同的,因此 React 标准的 API就能获取运行时 props 的获取/解析。 如下实现:


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Beginning Apache Struts

Beginning Apache Struts

Arnold Doray / Apress / 2006-02-20 / USD 44.99

Beginning Apache Struts will provide you a working knowledge of Apache Struts 1.2. This book is ideal for you Java programmers who have some JSP familiarity, but little or no prior experience with Ser......一起来看看 《Beginning Apache Struts》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具