TypeScript + React:正确定义 defaultProps

Posted

技术标签:

【中文标题】TypeScript + React:正确定义 defaultProps【英文标题】:TypeScript + React: defining defaultProps correctly 【发布时间】:2017-02-19 00:09:08 【问题描述】:

假设你这样定义你的组件:

interface IProps 
  req: string;
  defaulted: string;


class Comp extends React.Component<IProps, void> 
  static defaultProps = 
    defaulted: 'test',
  ;

  render() 
    const  defaulted  = this.props;

    return (
      <span>defaulted.toUpperCase()</span>
    );
  

当你想使用它时,TypeScript 需要你提供 defaulted 属性,即使它是在 defaultProps 中定义的:

<Comp req="something" />  // ERROR: TypeScript: prop 'defaulted' is required

但是,如果你像这样定义 props 接口:

interface IProps 
  req: string;
  defaulted?: string;  // note the ? here

那么你不能使用它:

render() 
  const  defaulted  = this.props;  // ERROR: prop 'defaulted' possibly undefined

  return (
    <span>defaulted.toUpperCase()</span>
  );

如何正确定义 IProps、defaultProps 和组件以使类型有意义?

编辑:

我正在使用strictNullChecks 标志。

【问题讨论】:

“我把它们默认了” ...你呢? 我很确定我做到了:static defaultProps: IDefaultProps = validate: () =&gt; null, defaultValue: '', ; 好吧,让我换个说法:它们似乎没有在您在问题中显示的代码中被默认。给minimal reproducible example。 如果添加 ? (就像您使用索引一样)它们将是可选的,并且您不会收到有关可能未定义的错误。然后,在你使用它们的地方默认它们的值。 @Stuart 但是我不能在组件中使用它 - TypeScript 抱怨它们可能是未定义的 【参考方案1】:

我有一个包含以下代码的示例(ComponentBase 只是我对 React.Component 的包装)。

编辑:更新代码以使用“strictNullChecks”设置

interface IExampleProps 
    name: string;
    otherPerson?: string;


/**
 * Class with props with default values
 *
 * @class Example
 * @extends ComponentBase<IComponentBaseSubProps, >
 */
export class Example extends ComponentBase<IExampleProps, > 
    public static defaultProps: IExampleProps = 
        otherPerson: "Simon",
        name: "Johnny"
    ;

    constructor(props: IExampleProps) 
        super(props);
    

    public render(): JSX.Element 
        const person: string = this.props.otherPerson === undefined ? "" : this.props.otherPerson;
        return(
            <div>
                <h1><small>Message by ComponentBaseSub: Hello this.props.name and person </small></h1>
            </div>
        );
    

我在使用 Visual Studio Code、TypeScript 2.0.3、TSLint 0.5.39 时没有任何问题。

【讨论】:

可能是因为this.props.otherPerson 可以成为undefined。尝试添加一个变量,比如const person: string = this.props.otherPerson;,看看它是否抱怨 @Idefixx 将该变量准确添加到“渲染”方法的主体中仍然不会导致您报告的问题。 你可以在github.com/boxstart/react-typescript-samples 上查看我的反应样本叉。示例 02 包含我上面示例中的可选属性和 defaultProps。如果您在使用此项目时仍然收到警告/错误,那么您可能需要在您的环境中查找设置。 啊啊啊,我正在使用strictNullChecks 标志。试试看 试过了,确实我也收到了消息。这并不是真正意外的行为,因为在对您的组件(jsx / tsx)的引用中,可以将属性设置为未定义,因此在您的渲染方法中,属性值仍然是“未定义”,尽管默认值在组件中。【参考方案2】:

更简单的是

<span>(defaulted as string).toUpperCase()</span>

属性的工作方式相同。如果Foo 需要barProp 属性而Parent 不需要并且通过defaultProps 得到它,Parent 的渲染方法可以做到

<Foo barProp=this.props.barProp as string />

【讨论】:

谢谢!使用 defaultProps 进行空检查会破坏使用 defaultProps 的好处【参考方案3】:

如果你确定 prop 会有一个默认值,你可以使用 null 断言类型操作符,像这样:

render() 
  const  defaulted  = this.props;
  return (
    <span>defaulted!.toUpperCase()</span>
  );

【讨论】:

以上是关于TypeScript + React:正确定义 defaultProps的主要内容,如果未能解决你的问题,请参考以下文章

如何正确定义样式组件的引用(React.RefObject<StyledComponentClass>)(对于 TypeScript)?

调度自定义事件并测试它是不是被正确触发(React TypeScript,Jest)

如何在 React 上正确使用带有样式组件画布的 TypeScript 类型

对 React 中如何使用接口(TypeScript)感到困惑

使用 TypeScript 声明 (*.d.ts) 和接口的正确方法?

Typescript/React onKeyPress 的正确参数类型是啥?