Idefixx Idefixx - 1 month ago 28
React JSX Question

TypeScript + React: defining defaultProps correctly

Say you define your component 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 component correctly so the types make sense?

EDIT:

I'm using the
strictNullChecks
flag.

Answer

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.

Comments