使用React。PropTypes在TypeScript React应用程序中是有意义的,或者这只是一个“腰带和背带”的例子?

因为组件类是用Props类型参数声明的:

interface Props {
    // ...
}
export class MyComponent extends React.Component<Props, any> { ... }

添加有什么真正的好处吗

static propTypes {
    myProp: React.PropTypes.string
}

类定义?


我想,在一些混乱的情况下,在编译时无法推断出道具的类型,那么在运行时查看使用propTypes生成的任何警告将是有用的。

其中一种情况是,当处理来自类型定义不可用的外部源的数据时,例如超出您控制的外部API。对于内部api,我认为如果类型定义还不可用,那么编写(或者更好地生成)类型定义是值得的。

除此之外,我真的没有看到任何好处(这就是为什么我个人从来没有使用过它)。


同时维护TypeScript类型和React类型的组件道具通常没有多大价值。同时使用PropTypes。

以下是一些这样做很有用的情况:

发布将被纯JavaScript使用的包(如组件库)。 接受并传递外部输入,例如来自API调用的结果。 使用来自库的数据可能没有足够或准确的类型(如果有的话)。

所以,这通常是一个问题,你可以在多大程度上信任你的编译时验证。

新版本的TypeScript现在可以根据React推断类型。PropTypes (PropTypes. inferprops),但结果类型可能难以在代码的其他地方使用或引用。


Typescript和PropTypes有不同的用途。Typescript在编译时验证类型,而proptype在运行时检查。

Typescript在你写代码的时候很有用:如果你给React组件传递了错误类型的参数,它会警告你,为函数调用自动补全等等。

当您测试组件如何与外部数据交互时,proptype非常有用,例如当您从API加载JSON时。PropTypes将帮助你调试(当在React的开发模式下)为什么你的组件失败,打印有用的消息,如:

Warning: Failed prop type: Invalid prop `id` of type `number` supplied to `Table`, expected `string`

尽管看起来Typescript和PropTypes做的是一样的事情,但它们实际上一点也不重叠。但是可以从Typescript自动生成PropTypes,这样你就不需要指定两次类型,参见示例:

https://github.com/milesj/babel-plugin-typescript-to-proptypes https://github.com/grncdr/ts-react-loader#what-it-does https://github.com/gcanti/prop-types-ts


正如@afonsoduarte所说。

我只是补充说,你也可以从PropTypes生成Typescript类型,就像这样:

const propTypes = {
  input: PropTypes.shape({
    id: PropTypes.number.isRequired,
    name: PropTypes.string.isRequired,
  }),
};

type MyComponentProps = PropTypes.InferProps<typeof propTypes>;

const MyComponent: FunctionComponent<MyComponentProps > = (props) => {
  // ...
}

MyComponent.propTypes = propTypes;

我最近在桥接本机代码时使用了Proptypes和TS。这个项目是在React端用TypeScript编写的,我把React端的原生组件抽象到它自己的文件中。没有必要担心PropTypes,这不是在它自己的文件,因为我已经通过TypeScript验证数据。

PropTypes用于处理Swift在事件回调时传入的外部数据。我尝试在这里使用TypeScript而不是PropTypes,但我在引用React组件时遇到了问题。

最终,它更容易实现PropTypes,而且似乎没有缺点,因为运行时的数据验证工作得非常好。

请参考这里的代码了解更多细节:

//CoreView.js
import React, {Component} from 'react';
import PropTypes from 'prop-types';

import {requireNativeComponent, UIManager, findNodeHandle} from 'react-native';

const COMPONENT_NAME = 'CoreView';
const RNCoreView = requireNativeComponent(COMPONENT_NAME);

export default class CoreView extends Component {
  static propTypes = {
    label: PropTypes.array,
    onUpdate: PropTypes.func,
  };
  _onUpdate = event => {
    if (this.props.onUpdate) {
      this.props.onUpdate(event.nativeEvent);
    }
  };
  render() {
    const {label, style} = this.props;
    return (
      <RNCoreView
        style={style}
        label={label}
        onUpdate={this._onUpdate}
        ref={ref => (this.ref = ref)}
      />
    );
  }
  update = (...args) => {
    UIManager.dispatchViewManagerCommand(
      findNodeHandle(this.ref),
      UIManager[COMPONENT_NAME].Commands.obtainLabelData,
      [...args],
    );
  };
}

在本土方面:

//CoreViewManager.m
#import <Foundation/Foundation.h>

#import "React/RCTViewManager.h"
@interface RCT_EXTERN_MODULE(CoreViewManager, RCTViewManager)

//Allow React to send data as props
RCT_EXPORT_VIEW_PROPERTY(onUpdate, RCTDirectEventBlock)

RCT_EXTERN_METHOD(
  obtainLabelData:(nonnull NSNumber *)node
  imageLocation:(nonnull NSString *)imageLocation
)

@end

还有……

import Foundation

@available(iOS 11.0, *)
@objc(CoreViewManager)
class CoreViewManager: RCTViewManager {
  override func view() -> UIView! {
    return CoreView()
  }
  
  @objc func obtainLabelData(_ node: NSNumber, imageLocation: NSString!) {
      
      DispatchQueue.main.async {
        let component = self.bridge.uiManager.view(
          forReactTag: node
        ) as! CoreView
        component.update(value: imageLocation)
      }
    }
}

@types/prop-types中的“InferPropTypes”可用于从PropTypes定义创建类型定义。检查下面的例子

import React from "react";
import PropTypes, { InferProps } from "prop-types";

const ComponentPropTypes = {
    title: PropTypes.string.isRequired,
    createdAt: PropTypes.instanceOf(Date),
    authorName: PropTypes.string.isRequired,
};

type ComponentTypes = InferProps<typeof ComponentPropTypes>;
const MyComponent = ({ authorName, createdAt, title }: ComponentTypes) => {
    return <span>Blog Card</span>;
};

MyComponent.propTypes = ComponentPropTypes;
export default MyComponent;