interface PageProps {
foo?: Function;
bar: number;
}
export class PageComponent extends React.Component<PageProps, {}> {
public static defaultProps: Partial<PageProps> = {
foo: () => alert('Did foo')
};
private doFoo() {
this.props.foo(); // Typescript Error: Object is possibly 'undefined'
}
public render(): JSX.Element {
return (
<div>
<span>Hello, world! The number is {this.props.bar}</span>
<button onClick={() => this.doFoo()}>Do the Foo</button>
</div>
);
}
}
Is there a way to tell Typescript that props.foo
will always be defined?
There is a very good SO question and answer that discusses how to properly define the types for props on a component. It even discusses how you would let TS know about defaultProps
on a stateless component.
However Typescript will still complain inside a regular component definition that your props might be undefined (as illustrated in my example above).
You can call it using a bang (this.props.foo!()
) and that prevents TS from throwing an error, but it also prevents any kind of type checking on whatever you've passed in. In the example above, not a big deal. In more complex code, it has already bitten me.
So I am currently implementing things like this instead:
private doFoo() {
if (this.props.foo) this.props.foo();
}
That has one drawback, which I think is rather important: It makes my code a little confusing. In reality, I always want to call this.props.foo()
, but it seems like, without investigating the class more closely, there are cases where nothing will happen inside the doFoo
method. (Yes I could add a comment explaining that the if
is only for Typescript to be happy, but I'd rather my code speak for itself when it can.)
My code becomes even more unnecessarily complex when I actually need to return something from this.props.foo()
.
I am currently using @types/react for my type definitions.