为用TypeScript编写的React组件生成PropTypes

时间:2019-01-06 09:01:57

标签: javascript reactjs typescript

我们正在为内部应用程序创建组件库。该库的旧版本是用JavaScriptJSX编写的,因此我们为所有类型安全的组件声明了propTypes
组件库的较新版本用TypeScript编写。为了确保类型安全,我们使用了PropTypes的接口,例如:-

interface Props {
    size?: 'small' | 'large';
    color?: string;
    text?: string;
}
export class MyComponent extends React.Component<Props, any> { ... }

这很好,因为使用这些组件的较新项目也是用TypeScript编写的(我们确实为所有组件类发布了d.ts文件)。现在,我们也需要更新旧项目中的组件库。由于他们没有使用TypeScript,因此类型安全性无法正常工作。他们仍然依靠旧的propTypes方法进行类型安全。

//Usage of MyComponent
<MyComponent size={20} color={'red'} text={'HelloWorld'} />
//Size must be one of 'small' or 'large' not the numeric value.

所以我的问题是,在非TypeScript项目中使用TypeScript(和tsx)编写的组件来处理此问题的方法是什么?

我已经找到了一些方法-

  • 为d.ts文件使用一些解析器
  • 为所有组件创建HoC
  • 手动编写propTypes以及所有组件的接口。

还有其他更清洁,更省力的方式吗?

1 个答案:

答案 0 :(得分:3)

一个完美的问题!我现在正在亲自调查这个确切的问题。

首先,我可以同意TypeScript不能100%替代PropType,因为:

  1. 如果您正在构建一个库,并且正被普通JavaScript中的项目使用,则类型不能帮助检测所有问题。

  2. PropTypes在运行时动态运行,而TypeScript检查仅静态运行。

  3. PropTypes可用于在运行时获取有关组件的信息,而类型定义在运行时会丢失。

我的搜索向我展示了以下可能性:

它允许在TypeScript编译期间实际生成PropType。它可作为Babel的插件。缺点是您必须使用Babel才能使用此功能。实际上,我已经发布了一个问题:Using the plugin without Babel?,但我怀疑是否有可能。

正如我从文档中看到的那样,这不是完全兼容的PropTypes生成器,而是替代品,它使用其自己的实现在运行时进行类型检查。我希望我的PropTypes与官方实现完全兼容。


您必须选择可以接受的条件以及您的项目要求是什么。如果您对使用Babel感到满意,我建议您首选。但是,如果只需要确保类型检查在运行时有效,则第二种方法可能是可行的。

对于我来说,我认为我现在必须同时保持TypeScript类型输入和手动PropTypes同步,因为我没有使用Babel,而且我真的不喜欢自定义PropTypes实现。

也许是晴天,我们会找到一些资源来实际在公司中编写自己的PropTypes生成器,并与所有人共享。


这是一个打字技巧,可用于使PropType与输入保持同步:

import * as PropTypes from 'prop-types';
import React, {PureComponent} from 'react';


export interface IconProps {
  name: string;
}

export class Icon extends PureComponent<IconProps> {

  static propTypes: { [key in keyof IconProps]: any } = {
    name: PropTypes.string
  };

  render() {
    return <i className="dc-icon">{this.props.name}</i>;
  }

}

这将强制propTypes对象具有与props接口完全相同的属性。