最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - TypeScript + React: defining defaultProps correctly - Stack Overflow

programmeradmin3浏览0评论

Say you define your ponent like so:

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>
    );
  }
}

when you want to use it, TypeScript wants the defaulted prop from you, even though it's defined in defaultProps:

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

However, if you define the props interface like so:

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

then you cannot use it in:

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

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

How to define the IProps, defaultProps and ponent correctly so the types make sense?

EDIT:

I'm using the strictNullChecks flag.

Say you define your ponent like so:

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>
    );
  }
}

when you want to use it, TypeScript wants the defaulted prop from you, even though it's defined in defaultProps:

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

However, if you define the props interface like so:

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

then you cannot use it in:

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

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

How to define the IProps, defaultProps and ponent correctly so the types make sense?

EDIT:

I'm using the strictNullChecks flag.

Share Improve this question edited Oct 11, 2016 at 14:04 Idefixx asked Oct 10, 2016 at 14:22 IdefixxIdefixx 4726 silver badges21 bronze badges 14
  • "I have them defaulted" ...do you? – jonrsharpe Commented Oct 10, 2016 at 14:25
  • I am pretty sure I do: static defaultProps: IDefaultProps = { validate: () => null, defaultValue: '', }; – Idefixx Commented Oct 10, 2016 at 14:26
  • Alright, let me rephrase: they don't appear to be defaulted in the code you show in the question. Give a minimal reproducible example. – jonrsharpe Commented Oct 10, 2016 at 14:26
  • If you add the ? (like you have with index) they will be optional and you won't get the error about being potentially undefined. Then, default their value where you use them. – rg88 Commented Oct 10, 2016 at 14:26
  • @Stuart but then I cannot use it within the ponent - TypeScript plains that they are potentially undefined – Idefixx Commented Oct 10, 2016 at 14:29
 |  Show 9 more ments

3 Answers 3

Reset to default 4

I have an example with the following code (ComponentBase is just my wrapper around React.Component).

Edit: updated code to work with 'strictNullChecks' setting

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>
        );
    }
}

I have no issues using Visual Studio Code, TypeScript 2.0.3, TSLint 0.5.39.

Even simpler is

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

Works the same way with properties. If Foo requires the barProp property but Parent does not and gets it through defaultProps, Parent's render method can do

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

If you know for sure the prop will have a default value, you can use the null assertion type operator, like this:

render() {
  const { defaulted } = this.props;
  return (
    <span>{defaulted!.toUpperCase()}</span>
  );
}
发布评论

评论列表(0)

  1. 暂无评论