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.
- "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
3 Answers
Reset to default 4I 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>
);
}