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

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

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


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

查看所有标签

猜你喜欢:

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

互联网产品运营:产品经理的10堂精英课

互联网产品运营:产品经理的10堂精英课

丁华、聂嵘海、王晶 / 电子工业出版社 / 2017-5 / 59

《互联网产品运营:产品经理的10堂精英课》共有10章,前9章分别从互联网产品运营的9个点入手,最后一章辅以案例,分析当下市场热门产品的运营模式。 第1章点明在运营产品之前需要经过缜密的策划,这样才能有明确的运营方向;第2章讲述产品运营的定位,有了准确的定位,运营才不会走偏;第3章描述用户运营,用户是一款产品的根本,没有用户,产品就是死的;第4章讲述内容运营的技巧,产品内容要怎么运营才能受到用......一起来看看 《互联网产品运营:产品经理的10堂精英课》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试